Merge remote-tracking branch 'upstream/develop' into aut-1885

This commit is contained in:
Oliver Spohngellert 2016-04-05 09:44:48 -04:00
commit ca35916ed2
113 changed files with 2431 additions and 2041 deletions

View File

@ -2,7 +2,7 @@ Manifest-Version: 1.0
OpenIDE-Module: org.sleuthkit.autopsy.core/10
OpenIDE-Module-Localizing-Bundle: org/sleuthkit/autopsy/core/Bundle.properties
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
AutoUpdate-Show-In-Client: true
AutoUpdate-Essential-Module: true

View File

@ -21,5 +21,5 @@ nbm.homepage=http://www.sleuthkit.org/
nbm.module.author=Brian Carrier
nbm.needs.restart=true
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/>
<run-dependency>
<release-version>3</release-version>
<specification-version>1.0</specification-version>
<specification-version>1.1</specification-version>
</run-dependency>
</dependency>
</module-dependencies>

View File

@ -1,7 +1,7 @@
/*
* Autopsy Forensic Browser
*
* Copyright 2013 Basis Technology Corp.
* Copyright 2011-2016 Basis Technology Corp.
* Contact: carrier <at> sleuthkit <dot> org
*
* Licensed under the Apache License, Version 2.0 (the "License");
@ -40,6 +40,7 @@ import org.sleuthkit.datamodel.TskCoreException;
public class GetTagNameAndCommentDialog extends JDialog {
private static final long serialVersionUID = 1L;
private static final String NO_TAG_NAMES_MESSAGE = NbBundle.getMessage(GetTagNameAndCommentDialog.class,
"GetTagNameAndCommentDialog.noTags");
private final HashMap<String, TagName> tagNames = new HashMap<>();
@ -47,8 +48,8 @@ public class GetTagNameAndCommentDialog extends JDialog {
public static class TagNameAndComment {
private TagName tagName;
private String comment;
private final TagName tagName;
private final String comment;
private TagNameAndComment(TagName tagName, String comment) {
this.tagName = tagName;
@ -67,8 +68,7 @@ public class GetTagNameAndCommentDialog extends JDialog {
/**
* Show the Tag Name and Comment Dialog and return the TagNameAndContent
* 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
* 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.autopsy.corecomponentinterfaces.DataSourceProcessorCallback;
import org.sleuthkit.autopsy.corecomponentinterfaces.DataSourceProcessor;
import org.sleuthkit.autopsy.coreutils.PlatformUtil;
import org.sleuthkit.autopsy.ingest.IngestJobSettings;
import org.sleuthkit.autopsy.ingest.IngestJobSettingsPanel;
import org.sleuthkit.autopsy.ingest.IngestManager;
@ -271,7 +272,10 @@ class AddImageWizardIngestConfigPanel implements WizardDescriptor.Panel<WizardDe
cleanupTask.disable();
// Get attention for the process finish
java.awt.Toolkit.getDefaultToolkit().beep(); //BEEP!
// this caused a crash on OS X
if (PlatformUtil.isWindowsOS() == true) {
java.awt.Toolkit.getDefaultToolkit().beep(); //BEEP!
}
AddImageWizardAddingProgressVisual panel = progressPanel.getComponent();
if (panel != null) {
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.title=Warning\: This will close the current case
CasePropertiesForm.imagesTable.columnModel.title1=Remove
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
*
* Copyright 2011-2015 Basis Technology Corp.
* Copyright 2011-2016 Basis Technology Corp.
* Contact: carrier <at> sleuthkit <dot> org
*
* Licensed under the Apache License, Version 2.0 (the "License");
@ -711,16 +711,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.
*
* @param imgPaths the paths of the image that being added
* @param imgId the ID of the image that being added
* @param timeZone the timeZone of the image where it's added
* @param imgPath The path of the image file.
* @param imgId The ID of the image.
* @param timeZone The time zone of the image.
*
* @deprecated As of release 4.0, replaced by {@link #notifyAddingDataSource(java.util.UUID) and
* {@link #notifyDataSourceAdded(org.sleuthkit.datamodel.Content, java.util.UUID) and
* {@link #notifyFailedAddingDataSource(java.util.UUID)}
* @deprecated As of release 4.0
*/
@Deprecated
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
* 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
* and times for the image, obtained from
* and times for the local drive, obtained from
* java.util.TimeZone.getID.
* @param ignoreFatOrphanFiles Whether to parse orphans if the image has a
* FAT filesystem.

View File

@ -43,7 +43,6 @@ public class LocalFilesDSProcessor implements DataSourceProcessor {
* TODO: Remove the setDataSourceOptionsCalled flag and the settings fields
* when the deprecated method setDataSourceOptions is removed.
*/
private String deviceId;
private List<String> localFilePaths;
private boolean setDataSourceOptionsCalled;
@ -123,10 +122,9 @@ public class LocalFilesDSProcessor implements DataSourceProcessor {
@Override
public void run(DataSourceProcessorProgressMonitor progressMonitor, DataSourceProcessorCallback callback) {
if (!setDataSourceOptionsCalled) {
deviceId = UUID.randomUUID().toString();
localFilePaths = Arrays.asList(configPanel.getContentPaths().split(LocalFilesPanel.FILES_SEP));
}
run(deviceId, "", localFilePaths, progressMonitor, callback);
run(UUID.randomUUID().toString(), configPanel.getFileSetName(), localFilePaths, progressMonitor, callback);
}
/**
@ -162,7 +160,7 @@ public class LocalFilesDSProcessor implements DataSourceProcessor {
* is a "best effort" cancellation, with no guarantees that the case
* database will be unchanged. If cancellation succeeded, the list of new
* data sources returned by the background task will be empty.
*
*
* TODO (AUT-1907): Implement cancellation by deleting rows added to the
* case database.
*/
@ -194,7 +192,8 @@ public class LocalFilesDSProcessor implements DataSourceProcessor {
*/
@Deprecated
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;
}

View File

@ -47,21 +47,30 @@
<Layout>
<DimensionLayout dim="0">
<Group type="103" groupAlignment="0" attributes="0">
<Group type="102" alignment="0" attributes="0">
<Component id="infoLabel" min="-2" max="-2" attributes="0"/>
<EmptySpace min="0" pref="0" max="32767" attributes="0"/>
</Group>
<Group type="102" alignment="1" attributes="0">
<Component id="jScrollPane2" pref="353" max="32767" attributes="0"/>
<Group type="103" groupAlignment="0" attributes="0">
<Group type="102" attributes="0">
<Component id="infoLabel" min="-2" max="-2" attributes="0"/>
<EmptySpace min="0" pref="0" max="32767" attributes="0"/>
</Group>
<Component id="jScrollPane2" pref="389" max="32767" attributes="0"/>
</Group>
<EmptySpace max="-2" attributes="0"/>
<Group type="103" groupAlignment="0" max="-2" 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>
<EmptySpace min="-2" pref="2" max="-2" attributes="0"/>
</Group>
<Group type="102" alignment="0" attributes="0">
<Component id="errorLabel" min="-2" max="-2" attributes="0"/>
<Group type="102" attributes="0">
<Group type="103" groupAlignment="0" 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"/>
</Group>
</Group>
@ -70,17 +79,23 @@
<Group type="103" groupAlignment="0" attributes="0">
<Group type="102" alignment="0" attributes="0">
<Component id="infoLabel" min="-2" max="-2" attributes="0"/>
<EmptySpace min="-2" pref="5" max="-2" attributes="0"/>
<Group type="103" groupAlignment="0" max="-2" attributes="0">
<Component id="jScrollPane2" min="-2" pref="82" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Group type="103" groupAlignment="1" attributes="0">
<Group type="102" 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"/>
</Group>
<Component id="jScrollPane2" min="-2" pref="82" max="-2" attributes="0"/>
</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"/>
<EmptySpace min="-2" pref="7" max="-2" attributes="0"/>
</Group>
</Group>
</DimensionLayout>
@ -151,5 +166,22 @@
</Property>
</Properties>
</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>
</Form>

View File

@ -18,6 +18,7 @@
*/
package org.sleuthkit.autopsy.casemodule;
import java.awt.Dialog;
import java.beans.PropertyChangeListener;
import java.beans.PropertyChangeSupport;
import java.io.File;
@ -32,6 +33,10 @@ import org.openide.util.NbBundle;
import org.sleuthkit.autopsy.corecomponentinterfaces.DataSourceProcessor;
import org.sleuthkit.autopsy.coreutils.MessageNotifyUtil;
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.coreutils.Logger;
import org.sleuthkit.autopsy.coreutils.PathValidator;
@ -47,6 +52,7 @@ class LocalFilesPanel extends JPanel {
private static LocalFilesPanel instance;
public static final String FILES_SEP = ",";
private static final Logger logger = Logger.getLogger(LocalFilesPanel.class.getName());
private String displayName = "";
/**
* Creates new form LocalFilesPanel
@ -67,6 +73,7 @@ class LocalFilesPanel extends JPanel {
localFileChooser.setMultiSelectionEnabled(true);
errorLabel.setVisible(false);
selectedPaths.setText("");
this.displayNameLabel.setText(NbBundle.getMessage(this.getClass(), "LocalFilesPanel.displayNameLabel.text"));
}
//@Override
@ -137,6 +144,8 @@ class LocalFilesPanel extends JPanel {
selectedPaths.setText("");
enableNext = false;
errorLabel.setVisible(false);
displayName = "";
this.displayNameLabel.setText(NbBundle.getMessage(this.getClass(), "LocalFilesPanel.displayNameLabel.text"));
}
@Override
@ -157,6 +166,10 @@ class LocalFilesPanel extends JPanel {
pcs.removePropertyChangeListener(pcl);
}
public String getFileSetName() {
return this.displayName;
}
@Override
public String toString() {
return NbBundle.getMessage(this.getClass(), "LocalFilesDSProcessor.toString.text");
@ -180,6 +193,8 @@ class LocalFilesPanel extends JPanel {
jScrollPane2 = new javax.swing.JScrollPane();
selectedPaths = new javax.swing.JTextArea();
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.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));
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);
this.setLayout(layout);
layout.setHorizontalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup()
.addComponent(infoLabel)
.addGap(0, 0, Short.MAX_VALUE))
.addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
.addComponent(jScrollPane2, javax.swing.GroupLayout.DEFAULT_SIZE, 353, Short.MAX_VALUE)
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup()
.addComponent(infoLabel)
.addGap(0, 0, Short.MAX_VALUE))
.addComponent(jScrollPane2, javax.swing.GroupLayout.DEFAULT_SIZE, 389, Short.MAX_VALUE))
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.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(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))
.addGroup(layout.createSequentialGroup()
.addComponent(errorLabel)
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(errorLabel)
.addGroup(layout.createSequentialGroup()
.addComponent(displayNameLabel)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
.addComponent(jButton1)))
.addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
);
layout.setVerticalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup()
.addComponent(infoLabel)
.addGap(5, 5, 5)
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false)
.addComponent(jScrollPane2, javax.swing.GroupLayout.PREFERRED_SIZE, 82, javax.swing.GroupLayout.PREFERRED_SIZE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING)
.addGroup(layout.createSequentialGroup()
.addComponent(selectButton)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addComponent(clearButton)))
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(errorLabel))
.addGap(36, 36, 36)
.addComponent(clearButton))
.addComponent(jScrollPane2, javax.swing.GroupLayout.PREFERRED_SIZE, 82, javax.swing.GroupLayout.PREFERRED_SIZE))
.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
@ -291,10 +326,20 @@ class LocalFilesPanel extends JPanel {
}//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
private javax.swing.JButton clearButton;
private javax.swing.JLabel displayNameLabel;
private javax.swing.JLabel errorLabel;
private javax.swing.JLabel infoLabel;
private javax.swing.JButton jButton1;
private javax.swing.JScrollPane jScrollPane1;
private javax.swing.JScrollPane jScrollPane2;
private javax.swing.JTextArea jTextArea1;

View File

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

View File

@ -2,7 +2,7 @@
*
* Autopsy Forensic Browser
*
* Copyright 2012 Basis Technology Corp.
* Copyright 2011-2016 Basis Technology Corp.
*
* Copyright 2012 42six Solutions.
* 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
* 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 localFile File/Dir that we are adding
* @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
* directory, another local file, or fscontent File),
* @param localFile File that we are adding
* @param trans A case database transaction.
*
* @return newly created local file object added to the database
*

View File

@ -1,7 +1,7 @@
/*
* Autopsy Forensic Browser
*
* Copyright 2011-2013 Basis Technology Corp.
* Copyright 2011-2016 Basis Technology Corp.
* Contact: carrier <at> sleuthkit <dot> org
*
* Licensed under the Apache License, Version 2.0 (the "License");
@ -385,7 +385,7 @@ public class DataContentViewerHex extends javax.swing.JPanel implements DataCont
/**
* 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) {
if (this.dataSource == null) {

View File

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

View File

@ -18,6 +18,7 @@
*/
package org.sleuthkit.autopsy.corecomponents;
import com.google.common.io.Files;
import java.awt.Dimension;
import java.awt.Image;
import java.awt.image.BufferedImage;
@ -680,6 +681,7 @@ public class GstVideoPanel extends MediaViewVideoPanel {
progressLabel.setText(NbBundle.getMessage(this.getClass(), "GstVideoPanel.progress.buffering"));
progress.start(100);
try {
Files.createParentDirs(tempFile);
return ContentUtils.writeToFile(sourceFile, tempFile, progress, this, true);
} catch (IOException ex) {
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 javax.swing.JPanel;
import org.sleuthkit.autopsy.coreutils.Logger;
import org.sleuthkit.autopsy.modules.filetypeid.FileTypeDetector;
import org.sleuthkit.datamodel.AbstractFile;
import org.sleuthkit.datamodel.TskCoreException;
/**
* 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
public boolean isSupported(AbstractFile file) {
/*
* TODO (AUT-2042): Is this the logic we want?
*/
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)) {
SortedSet<String> mimeTypes = new TreeSet<>(getMimeTypes());
String mimeType = file.getMIMEType();
if (nonNull(mimeType)) {
return mimeTypes.contains(mimeType);
} else {
return getExtensionsList().contains("." + extension);
try {
String mimeType = new FileTypeDetector().detect(file);
if (nonNull(mimeType)) {
return mimeTypes.contains(mimeType);
}
} 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;
}

View File

@ -1,7 +1,20 @@
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
* Autopsy Forensic Browser
*
* Copyright 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;
@ -467,7 +480,8 @@ public final class MultiUserSettingsPanel extends javax.swing.JPanel {
/**
* 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) {
for (JTextField textField : textFields) {

View File

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

View File

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

View File

@ -32,10 +32,10 @@ import java.io.InputStream;
import java.nio.file.Paths;
import java.text.MessageFormat;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import java.util.Objects;
import static java.util.Objects.nonNull;
import java.util.SortedSet;
import java.util.TreeSet;
@ -78,7 +78,7 @@ public class ImageUtils {
/**
* 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_MEDIUM = 100;
@ -86,12 +86,11 @@ public class ImageUtils {
private static final BufferedImage DEFAULT_THUMBNAIL;
private static final String IMAGE_GIF_MIME = "image/gif"; //NOI18N NON-NLS
private static final SortedSet<String> GIF_MIME_SET = ImmutableSortedSet.copyOf(new String[]{IMAGE_GIF_MIME});
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"});
private static final List<String> SUPPORTED_IMAGE_EXTENSIONS;
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;
@ -99,9 +98,9 @@ public class ImageUtils {
ImageIO.scanForPlugins();
BufferedImage tempImage;
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) {
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;
}
DEFAULT_THUMBNAIL = tempImage;
@ -110,23 +109,22 @@ public class ImageUtils {
boolean openCVLoadedTemp;
try {
System.loadLibrary(Core.NATIVE_LIBRARY_NAME);
if (System.getProperty("os.arch").equals("amd64") || System.getProperty("os.arch").equals("x86_64")) { //NOI18N NON-NLS
System.loadLibrary("opencv_ffmpeg248_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"); //NON-NLS
} else {
System.loadLibrary("opencv_ffmpeg248"); //NOI18N NON-NLS
System.loadLibrary("opencv_ffmpeg248"); //NON-NLS
}
openCVLoadedTemp = true;
} catch (UnsatisfiedLinkError e) {
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
}
openCVLoaded = openCVLoadedTemp;
SUPPORTED_IMAGE_EXTENSIONS = Arrays.asList(ImageIO.getReaderFileSuffixes());
SUPPORTED_IMAGE_MIME_TYPES = new TreeSet<>(Arrays.asList(ImageIO.getReaderMIMETypes()));
/*
* 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-portable-graymap", //NON-NLS
"image/x-portable-bitmap", //NON-NLS
"application/x-123")); //TODO: is this correct? -jm //NOI18N NON-NLS
SUPPORTED_IMAGE_MIME_TYPES.removeIf("application/octet-stream"::equals); //NOI18N NON-NLS
"application/x-123")); //TODO: is this correct? -jm //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
= 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() {
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
* not generate 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.
* not generate a content based thumbnail.
*
* @return the default thumbnail
*/
@ -196,9 +181,6 @@ public class ImageUtils {
*/
public static boolean thumbnailSupported(Content content) {
if (content.getSize() == 0) {
return false;
}
if (!(content instanceof AbstractFile)) {
return false;
}
@ -206,79 +188,84 @@ public class ImageUtils {
return VideoUtils.isVideoThumbnailSupported(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
* for.
*/
public static boolean isImageThumbnailSupported(AbstractFile file) {
return isMediaThumbnailSupported(file, SUPPORTED_IMAGE_MIME_TYPES, SUPPORTED_IMAGE_EXTENSIONS, CONDITIONAL_MIME_TYPES)
|| hasImageFileHeader(file);
return isMediaThumbnailSupported(file, "image/", SUPPORTED_IMAGE_MIME_TYPES, SUPPORTED_IMAGE_EXTENSIONS) || hasImageFileHeader(file);//NON-NLS
}
/**
* Checks the MIME type of a file to determine whether it is a GIF. If the
* MIME type is not known, checks for a "gif" extension.
* Checks the MIME type and/or extension of a file to determine whether it
* 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) {
String mimeType = file.getMIMEType();
if (nonNull(mimeType)) {
return IMAGE_GIF_MIME.equalsIgnoreCase(mimeType);
} else {
return "gif".equalsIgnoreCase(file.getNameExtension()); //NOI18N
}
return isMediaThumbnailSupported(file, null, GIF_MIME_SET, GIF_EXTENSION_LIST);
}
/**
* 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
* VideoUtils both implement/extend some base interface/abstract class. That
* would be the natural place to put this.
*
* @param file
* @param supportedMimeTypes a set of mimetypes that the could have to be
* supported
* @param supportedExtension a set of extensions a file could have to be
* supported if the mime lookup fails or is
* inconclusive
* @param conditionalMimes a set of mimetypes that a file could have to be
* supoprted if it also has a supported extension
* @param file the AbstractFile to test
* @param mimeTypePrefix a MIME 'top-level type name' such as "image/",
* including the "/". In addition to the list of
* supported MIME types, any type that starts with
* this prefix will be regarded as supported
* @param supportedMimeTypes a collection of mimetypes that are supported
* @param supportedExtension a collection of extensions that are supported
*
* @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) {
if (file.getSize() == 0) {
static boolean isMediaThumbnailSupported(AbstractFile file, String mimeTypePrefix, final Collection<String> supportedMimeTypes, final List<String> supportedExtension) {
if (false == file.isFile() || file.getSize() <= 0) {
return false;
}
String mimeType = file.getMIMEType();
String extension = file.getNameExtension();
if (nonNull(mimeType)) {
return supportedMimeTypes.contains(mimeType)
|| (conditionalMimes.contains(mimeType.toLowerCase())
&& supportedExtension.contains(extension));
if (StringUtils.isNotBlank(extension) && supportedExtension.contains(extension)) {
return true;
} 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
*
* @throws FileTypeDetectorInitException if a initializing the
* @throws FileTypeDetectorInitException if initializing the
* FileTypeDetector failed.
*/
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
* 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
* @param content the content to generate a thumbnail for
* @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.
@ -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
* thumbnail if it is not already cached.
*
* @param content
* @param iconSize
* @param content the content to generate a thumbnail for
* @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
* 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
* file may not exist.
* Get the location of the cached thumbnail for a file with the given fileID
* as a java {@link File}. The returned File may not exist on disk yet.
*
* @param id
*
* @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
* @param fileID the fileID to get the cached thumbnail location for
*
* @return a File object representing the location of the cached thumbnail.
* 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) {
try {
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) {
LOGGER.log(Level.WARNING, "Could not get cached thumbnail location. No case is open."); //NON-NLS
return null;
}
}
/**
* Do a direct check to see if the given file has an image file header.
* 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.
*/
@ -424,7 +354,7 @@ public class ImageUtils {
/**
* 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
*/
@ -449,7 +379,7 @@ public class ImageUtils {
/**
* 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
*/
@ -481,7 +411,7 @@ public class ImageUtils {
if (bytesRead != buffLength) {
//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;
}
@ -498,7 +428,7 @@ public class ImageUtils {
*/
static public int getImageWidth(AbstractFile file) throws IOException {
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)
);
}
@ -515,7 +445,7 @@ public class ImageUtils {
*/
static public int getImageHeight(AbstractFile file) throws IOException {
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)
);
}
@ -537,7 +467,7 @@ public class ImageUtils {
/**
* Private template method designed to be used as the implementation of
* 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 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
* task, monitoring its progress, and using its result.
*
* @param file the file to create a thumbnail for
* @param iconSize the size of the thumbnail
* @param file The file to create a thumbnail for.
* @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.
*/
@ -612,7 +543,7 @@ public class ImageUtils {
*/
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 File cacheFile;
@ -646,7 +577,7 @@ public class ImageUtils {
return SwingFXUtils.toFXImage(cachedThumbnail, null);
}
} 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.
}
}
@ -666,7 +597,7 @@ public class ImageUtils {
if (defaultOnFailure) {
thumbnail = DEFAULT_THUMBNAIL;
} 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);
} catch (IllegalArgumentException | OutOfMemoryError e) {
// 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 width = bufferedImage.getWidth();
@ -696,11 +627,11 @@ public class ImageUtils {
try {
thumbnail = ScalrWrapper.cropImage(bufferedImage, cropWidth, cropHeight);
} 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) {
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;
}
}
@ -733,19 +664,20 @@ public class ImageUtils {
}
ImageIO.write(thumbnail, FORMAT, cacheFile);
} 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
}
});
}
}
/**
* Create a new {@link Task} that will read the fileinto memory as an
* Create a new {@link Task} that will read the file into memory as an
* {@link javafx.scene.image.Image}
*
* Note: the returned task is suitable for running in a background thread,
* 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
*
@ -779,7 +711,7 @@ public class ImageUtils {
*/
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;
// private ImageReader reader;
@ -815,7 +747,7 @@ public class ImageUtils {
try {
bufferedImage = imageReader.read(0, param); //should always be same bufferedImage object
} 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 {
imageReader.removeIIOReadProgressListener(ReadImageTaskBase.this);
}
@ -901,15 +833,85 @@ public class ImageUtils {
*
* @param content
*
* @return
* @return the unique path for the content, or if that fails, just the name.
*/
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
LOGGER.log(Level.SEVERE, "Failed to get unique path for " + contentName, tskCoreException); //NON-NLS
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
*
* Copyright 2012 Basis Technology Corp.
* Copyright 2011-2016 Basis Technology Corp.
* Contact: carrier <at> sleuthkit <dot> org
*
* Licensed under the Apache License, Version 2.0 (the "License");
@ -25,14 +25,12 @@ import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.logging.Level;
import org.sleuthkit.autopsy.coreutils.Logger;
import org.sleuthkit.autopsy.coreutils.LnkEnums.CommonCLSIDS;
import org.sleuthkit.autopsy.coreutils.LnkEnums.DriveType;
import org.sleuthkit.autopsy.coreutils.LnkEnums.NetworkProviderType;
/**
*
* @author dfickling Parse lnk files using documentation from
* Parse lnk files using documentation from:
* http://msdn.microsoft.com/en-us/library/dd871305(v=prot.13).aspx
* http://msdn.microsoft.com/en-us/library/windows/desktop/cc144090(v=vs.85).aspx#unknown_74413
* http://blog.0x01000000.org/2010/08/10/lnk-parsing-youre-doing-it-wrong-i/
@ -67,12 +65,12 @@ public class JLnkParser {
int showCommand = bb.getInt();
short hotkey = bb.getShort();
bb.get(new byte[10]); // reserved (???)
List<String> linkTargetIdList = new ArrayList<String>();
List<String> linkTargetIdList = new ArrayList<>();
if ((linkFlags & LnkEnums.LinkFlags.HasLinkTargetIDList.getFlag())
== LnkEnums.LinkFlags.HasLinkTargetIDList.getFlag()) {
int idListSize = bb.getShort();
int bytesRead = 0;
List<byte[]> linkTargetIdListBytes = new ArrayList<byte[]>();
List<byte[]> linkTargetIdListBytes = new ArrayList<>();
while (true) {
short itemIdSize = bb.getShort();
if (itemIdSize == 0) {
@ -82,7 +80,7 @@ public class JLnkParser {
byte[] theArray = new byte[itemIdSize - 2];
bb.get(theArray); // an idlist data object
linkTargetIdListBytes.add(theArray);
bytesRead = bytesRead + itemIdSize;
bytesRead += itemIdSize;
}
linkTargetIdList = parseLinkTargetIdList(linkTargetIdListBytes);
}
@ -272,7 +270,7 @@ public class JLnkParser {
}
private List<String> parseLinkTargetIdList(List<byte[]> idList) {
List<String> ret = new ArrayList<String>();
List<String> ret = new ArrayList<>();
if (!idList.isEmpty()) {
CommonCLSIDS clsid = CommonCLSIDS.valueOf(Arrays.copyOfRange(idList.remove(0), 2, 18));
switch (clsid) {
@ -295,7 +293,7 @@ public class JLnkParser {
}
private List<String> parsePathElements(List<byte[]> idList) {
List<String> ret = new ArrayList<String>();
List<String> ret = new ArrayList<>();
for (byte[] pathElement : idList) {
ByteBuffer bb = ByteBuffer.wrap(pathElement);
bb.order(ByteOrder.LITTLE_ENDIAN);

View File

@ -1,7 +1,7 @@
/*
* Autopsy Forensic Browser
*
* Copyright 2015 Basis Technology Corp.
* Copyright 2011-2016 Basis Technology Corp.
* Contact: carrier <at> sleuthkit <dot> org
*
* Licensed under the Apache License, Version 2.0 (the "License");
@ -60,7 +60,8 @@ public class UNCPathUtilities {
/**
* 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:
* \\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
* 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
* hostname, if it can resolve the hostname. Given
* \\10.11.12.13\some\folder, the result will be \\TEDS_COMPUTER\some\folder
* if the IP address 10.11.12.13 belongs to a machine with the hostname
* TEDS_COMPUTER and the local machine is able to resolve the hostname.
* "\\10.11.12.13\some\folder", the result will be
* "\\TEDS_COMPUTER\some\folder" if the IP address 10.11.12.13 belongs to a
* 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
*
@ -186,9 +188,10 @@ public class UNCPathUtilities {
/**
* Takes a UNC path that may have an IP address in it and converts it to
* hostname, if it can resolve the hostname. Given
* \\10.11.12.13\some\folder, the result will be \\TEDS_COMPUTER\some\folder
* if the IP address 10.11.12.13 belongs to a machine with the hostname
* TEDS_COMPUTER and the local machine is able to resolve the hostname.
* "\\10.11.12.13\some\folder", the result will be
* "\\TEDS_COMPUTER\some\folder" if the IP address 10.11.12.13 belongs to a
* 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
*
@ -263,6 +266,11 @@ public class UNCPathUtilities {
*/
synchronized private Map<String, String> getMappedDrives() {
Map<String, String> driveMap = new HashMap<>();
if (PlatformUtil.isWindowsOS() == false) {
return driveMap;
}
File mappedDrive = Paths.get(System.getenv(TEMP_FOLDER), nameString + MAPPED_DRIVES).toFile();
try {
Files.deleteIfExists(mappedDrive.toPath());

View File

@ -60,10 +60,17 @@ public class VideoUtils {
"flm", "tmv", "4xm"); //NON-NLS
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
"video/mp4", "video/x-ms-wmv", "video/mpeg", "video/asf")); //NON-NLS
private static final List<String> CONDITIONAL_MIME_TYPES = Arrays.asList("application/octet-stream"); //NON-NLS
Arrays.asList("application/x-shockwave-flash",
"video/x-m4v",
"video/x-flv",
"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() {
return SUPPORTED_VIDEO_EXTENSIONS;
@ -89,7 +96,7 @@ public class VideoUtils {
}
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",

View File

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

View File

@ -286,25 +286,19 @@ public class BlackboardArtifactNode extends DisplayableItemNode {
* are put
* @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) {
try {
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
if (attributeTypeID == ATTRIBUTE_TYPE.TSK_PATH_ID.getTypeID()
|| attributeTypeID == ATTRIBUTE_TYPE.TSK_TAGGED_ARTIFACT.getTypeID()
|| attributeTypeID == ATTRIBUTE_TYPE.TSK_ASSOCIATED_ARTIFACT.getTypeID()
|| attributeTypeID == ATTRIBUTE_TYPE.TSK_SET_NAME.getTypeID()) {
} else if (attributeTypeID == ATTRIBUTE_TYPE.TSK_DATETIME.getTypeID()
|| attributeTypeID == ATTRIBUTE_TYPE.TSK_DATETIME_ACCESSED.getTypeID()
|| attributeTypeID == ATTRIBUTE_TYPE.TSK_DATETIME_CREATED.getTypeID()
|| 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));
continue;
} else if (attribute.getAttributeType().getValueType() == BlackboardAttribute.TSK_BLACKBOARD_ATTRIBUTE_VALUE_TYPE.DATETIME) {
map.put(attribute.getAttributeType().getDisplayName(), ContentUtils.getStringTime(attribute.getValueLong(), associated));
} else if (artifact.getArtifactTypeID() == ARTIFACT_TYPE.TSK_TOOL_OUTPUT.getTypeID()
&& attributeTypeID == ATTRIBUTE_TYPE.TSK_TEXT.getTypeID()) {
/*
@ -318,9 +312,9 @@ public class BlackboardArtifactNode extends DisplayableItemNode {
if (value.length() > 512) {
value = value.substring(0, 512);
}
map.put(attribute.getAttributeTypeDisplayName(), value);
map.put(attribute.getAttributeType().getDisplayName(), value);
} else {
map.put(attribute.getAttributeTypeDisplayName(), attribute.getDisplayString());
map.put(attribute.getAttributeType().getDisplayName(), attribute.getDisplayString());
}
}
} catch (TskException ex) {

View File

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

View File

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

View File

@ -55,7 +55,7 @@ public class VirtualDirectoryNode extends AbstractAbstractFileNode<VirtualDirect
//set icon for name, special case for some built-ins
if (name.equals(VirtualDirectory.NAME_UNALLOC)) {
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
} else if (name.equals(VirtualDirectory.NAME_CARVED)) {
this.setIconBaseWithExtension("org/sleuthkit/autopsy/images/Folder-icon.png"); //TODO NON-NLS

View File

@ -1,7 +1,7 @@
/*
* Autopsy Forensic Browser
*
* Copyright 2014 Basis Technology Corp.
* Copyright 2011-2016 Basis Technology Corp.
* Contact: carrier <at> sleuthkit <dot> org
*
* Licensed under the Apache License, Version 2.0 (the "License");
@ -26,7 +26,6 @@ import java.util.Collection;
import java.util.HashSet;
import java.util.List;
import java.util.logging.Level;
import org.openide.util.Exceptions;
import org.openide.util.NbBundle;
import org.sleuthkit.autopsy.casemodule.Case;
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.Logger;
import org.sleuthkit.autopsy.coreutils.MessageNotifyUtil;
import org.sleuthkit.autopsy.ingest.IngestModule;
import org.sleuthkit.autopsy.ingest.IngestServices;
import org.sleuthkit.autopsy.ingest.ModuleContentEvent;
import org.sleuthkit.autopsy.ingest.ModuleDataEvent;
@ -69,11 +67,12 @@ public final class ExternalResultsImporter {
* Import results generated by a process external to Autopsy into Autopsy.
*
* @param results A standard representation of results data (e.g.,
* 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
* messages are already logged but are provided to allow the caller to
* provide additional user feedback via the Autopsy user interface.
* messages are already logged but are provided to allow the caller
* to provide additional user feedback via the Autopsy user
* interface.
*/
public List<ErrorInfo> importResults(ExternalResults results) {
blackboard = Case.getCurrentCase().getServices().getBlackboard();
@ -133,7 +132,7 @@ public final class ExternalResultsImporter {
for (ExternalResults.Artifact artifactData : results.getArtifacts()) {
try {
// Add the artifact to the case database.
int artifactTypeId = caseDb.getArtifactTypeID(artifactData.getType());
int artifactTypeId = caseDb.getArtifactType(artifactData.getType()).getTypeID();
if (artifactTypeId == -1) {
artifactTypeId = caseDb.addBlackboardArtifactType(artifactData.getType(), artifactData.getType()).getTypeID();
}
@ -147,20 +146,20 @@ public final class ExternalResultsImporter {
BlackboardAttribute.Type attributeType = caseDb.getAttributeType(attributeData.getType());
if (attributeType == null) {
switch (attributeData.getValueType()) {
case "text": //NON-NLS
attributeType = caseDb.addArtifactAttributeType(attributeData.getType(), BlackboardAttribute.TSK_BLACKBOARD_ATTRIBUTE_VALUE_TYPE.fromLabel("String"), attributeData.getType()); //NON-NLS
break;
case "int32": //NON-NLS
attributeType = caseDb.addArtifactAttributeType(attributeData.getType(), BlackboardAttribute.TSK_BLACKBOARD_ATTRIBUTE_VALUE_TYPE.fromLabel("Integer"), attributeData.getType()); //NON-NLS
break;
case "int64": //NON-NLS
attributeType = caseDb.addArtifactAttributeType(attributeData.getType(), BlackboardAttribute.TSK_BLACKBOARD_ATTRIBUTE_VALUE_TYPE.fromLabel("Long"), attributeData.getType()); //NON-NLS
break;
case "double": //NON-NLS
attributeType = caseDb.addArtifactAttributeType(attributeData.getType(), BlackboardAttribute.TSK_BLACKBOARD_ATTRIBUTE_VALUE_TYPE.fromLabel("Double"), attributeData.getType()); //NON-NLS
break;
case "datetime": //NON-NLS
attributeType = caseDb.addArtifactAttributeType(attributeData.getType(), BlackboardAttribute.TSK_BLACKBOARD_ATTRIBUTE_VALUE_TYPE.fromLabel("DateTime"), attributeData.getType()); //NON-NLS
case "text": //NON-NLS
attributeType = caseDb.addArtifactAttributeType(attributeData.getType(), BlackboardAttribute.TSK_BLACKBOARD_ATTRIBUTE_VALUE_TYPE.fromLabel("String"), attributeData.getType()); //NON-NLS
break;
case "int32": //NON-NLS
attributeType = caseDb.addArtifactAttributeType(attributeData.getType(), BlackboardAttribute.TSK_BLACKBOARD_ATTRIBUTE_VALUE_TYPE.fromLabel("Integer"), attributeData.getType()); //NON-NLS
break;
case "int64": //NON-NLS
attributeType = caseDb.addArtifactAttributeType(attributeData.getType(), BlackboardAttribute.TSK_BLACKBOARD_ATTRIBUTE_VALUE_TYPE.fromLabel("Long"), attributeData.getType()); //NON-NLS
break;
case "double": //NON-NLS
attributeType = caseDb.addArtifactAttributeType(attributeData.getType(), BlackboardAttribute.TSK_BLACKBOARD_ATTRIBUTE_VALUE_TYPE.fromLabel("Double"), attributeData.getType()); //NON-NLS
break;
case "datetime": //NON-NLS
attributeType = caseDb.addArtifactAttributeType(attributeData.getType(), BlackboardAttribute.TSK_BLACKBOARD_ATTRIBUTE_VALUE_TYPE.fromLabel("DateTime"), attributeData.getType()); //NON-NLS
}
}
@ -216,13 +215,7 @@ public final class ExternalResultsImporter {
ExternalResultsImporter.logger.log(Level.SEVERE, errorMessage);
this.errors.add(new ErrorInfo(ExternalResultsImporter.class.getName(), errorMessage));
}
} catch (TskCoreException 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) {
} catch (TskCoreException | TskDataException ex) {
String errorMessage = NbBundle.getMessage(this.getClass(),
"ExternalResultsImporter.importArtifacts.errMsg2.text",
artifactData.getType(), artifactData.getSourceFilePath());
@ -299,15 +292,6 @@ public final class ExternalResultsImporter {
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) {
ExternalResultsImporter.logger.log(Level.SEVERE, errorMessage);
this.errors.add(new ErrorInfo(this.getClass().getName(), errorMessage));

View File

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

View File

@ -18,7 +18,7 @@ DateSearchPanel.jLabel1.text=to
DateSearchPanel.dateFromTextField.text=
DateSearchPanel.dateFromButtonCalendar.text=
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=
SizeSearchPanel.sizeCheckBox.text=Size:
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.metadata=Metadata
FileSearchPanel.filterTitle.knownStatus=Known Status
FileSearchPanel.searchButton.text=Search
FileSearchPanel.search.results.title=File Search Results {0}
FileSearchPanel.search.results.pathText=Filename Search Results\:
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.greaterThan=greater 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
KnownStatusSearchPanel.knownCheckBox.text=\u65E2\u77E5\u30B9\u30C6\u30FC\u30BF\u30B9\uFF1A
KnownStatusSearchPanel.knownBadOptionCheckBox.text=\u65E2\u77E5\u306E\u60AA\u8CEA
KnownStatusSearchPanel.knownOptionCheckBox.text=\u65E2\u77E5\uFF08NSRL\u307E\u305F\u306F\u305D\u306E\u4ED6\uFF09
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
DateSearchPanel.dateCheckBox.text=\u65E5\u4ED8\uFF1A
DateSearchPanel.jLabel4.text=\u30BF\u30A4\u30E0\u30BE\u30FC\u30F3\uFF1A
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.createdCheckBox.text=\u4F5C\u6210\u6E08\u307F
DateSearchPanel.accessedCheckBox.text=\u30A2\u30AF\u30BB\u30B9\u6E08\u307F
DateSearchPanel.changedCheckBox.text=\u5909\u66F4\u6E08\u307F
DateSearchPanel.modifiedCheckBox.text=\u4FEE\u6B63\u6E08\u307F
OpenIDE-Module-Name=\u30d5\u30a1\u30a4\u30eb\u691c\u7d22
KnownStatusSearchPanel.knownCheckBox.text=\u65e2\u77e5\u30b9\u30c6\u30fc\u30bf\u30b9\uff1a
KnownStatusSearchPanel.knownBadOptionCheckBox.text=\u65e2\u77e5\u306e\u60aa\u8cea
KnownStatusSearchPanel.knownOptionCheckBox.text=\u65e2\u77e5\uff08NSRL\u307e\u305f\u306f\u305d\u306e\u4ed6\uff09
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
DateSearchPanel.dateCheckBox.text=\u65e5\u4ed8\uff1a
DateSearchPanel.jLabel4.text=\u30bf\u30a4\u30e0\u30be\u30fc\u30f3\uff1a
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.createdCheckBox.text=\u4f5c\u6210\u6e08\u307f
DateSearchPanel.accessedCheckBox.text=\u30a2\u30af\u30bb\u30b9\u6e08\u307f
DateSearchPanel.changedCheckBox.text=\u5909\u66f4\u6e08\u307f
DateSearchPanel.modifiedCheckBox.text=\u4fee\u6b63\u6e08\u307f
DateSearchPanel.jLabel1.text=to
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>
SizeSearchPanel.sizeCheckBox.text=\u30B5\u30A4\u30BA\uFF1A
NameSearchPanel.cutMenuItem.text=\u30AB\u30C3\u30C8
NameSearchPanel.copyMenuItem.text=\u30B3\u30D4\u30FC
NameSearchPanel.pasteMenuItem.text=\u8CBC\u308A\u4ED8\u3051
NameSearchPanel.selectAllMenuItem.text=\u3059\u3079\u3066\u9078\u629E
SizeSearchPanel.selectAllMenuItem.text=\u3059\u3079\u3066\u9078\u629E
SizeSearchPanel.pasteMenuItem.text=\u8CBC\u308A\u4ED8\u3051
SizeSearchPanel.copyMenuItem.text=\u30B3\u30D4\u30FC
SizeSearchPanel.cutMenuItem.text=\u30AB\u30C3\u30C8
DateSearchPanel.cutMenuItem.text=\u30AB\u30C3\u30C8
DateSearchPanel.selectAllMenuItem.text=\u3059\u3079\u3066\u9078\u629E
DateSearchPanel.pasteMenuItem.text=\u8CBC\u308A\u4ED8\u3051
DateSearchPanel.copyMenuItem.text=\u30B3\u30D4\u30FC
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.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.filterTitle.name=\u540D\u524D
FileSearchPanel.filterTitle.metadata=\u30E1\u30BF\u30C7\u30FC\u30BF
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.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.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.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
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
SearchNode.getName.text=\u691C\u7D22\u7D50\u679C
SizeSearchPanel.sizeCompareComboBox.equalTo=\u4E0B\u8A18\u3068\u7B49\u3057\u3044
SizeSearchPanel.sizeCompareComboBox.greaterThan=\u4E0B\u8A18\u3088\u308A\u5927\u304D\u3044
SizeSearchPanel.sizeCompareComboBox.lessThan=\u4E0B\u8A18\u3088\u308A\u5C0F\u3055\u3044
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>
SizeSearchPanel.sizeCheckBox.text=\u30b5\u30a4\u30ba\uff1a
NameSearchPanel.cutMenuItem.text=\u30ab\u30c3\u30c8
NameSearchPanel.copyMenuItem.text=\u30b3\u30d4\u30fc
NameSearchPanel.pasteMenuItem.text=\u8cbc\u308a\u4ed8\u3051
NameSearchPanel.selectAllMenuItem.text=\u3059\u3079\u3066\u9078\u629e
SizeSearchPanel.selectAllMenuItem.text=\u3059\u3079\u3066\u9078\u629e
SizeSearchPanel.pasteMenuItem.text=\u8cbc\u308a\u4ed8\u3051
SizeSearchPanel.copyMenuItem.text=\u30b3\u30d4\u30fc
SizeSearchPanel.cutMenuItem.text=\u30ab\u30c3\u30c8
DateSearchPanel.cutMenuItem.text=\u30ab\u30c3\u30c8
DateSearchPanel.selectAllMenuItem.text=\u3059\u3079\u3066\u9078\u629e
DateSearchPanel.pasteMenuItem.text=\u8cbc\u308a\u4ed8\u3051
DateSearchPanel.copyMenuItem.text=\u30b3\u30d4\u30fc
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.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.filterTitle.name=\u540d\u524d
FileSearchPanel.filterTitle.metadata=\u30e1\u30bf\u30c7\u30fc\u30bf
FileSearchPanel.filterTitle.knownStatus=\u65e2\u77e5\u30b9\u30c6\u30fc\u30bf\u30b9
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.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.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.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
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
SizeSearchPanel.sizeCompareComboBox.equalTo=\u4e0b\u8a18\u3068\u7b49\u3057\u3044
SizeSearchPanel.sizeCompareComboBox.greaterThan=\u4e0b\u8a18\u3088\u308a\u5927\u304d\u3044
SizeSearchPanel.sizeCompareComboBox.lessThan=\u4e0b\u8a18\u3088\u308a\u5c0f\u3055\u3044

View File

@ -55,86 +55,93 @@
<DimensionLayout dim="0">
<Group type="103" groupAlignment="0" attributes="0">
<Group type="102" attributes="0">
<Component id="dateCheckBox" min="-2" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Component id="dateFromTextField" min="-2" pref="92" max="-2" attributes="0"/>
<EmptySpace min="-2" pref="0" max="-2" attributes="0"/>
<Component id="dateFromButtonCalendar" min="-2" max="-2" attributes="0"/>
<EmptySpace type="unrelated" min="-2" max="-2" attributes="0"/>
<Component id="jLabel1" min="-2" max="-2" attributes="0"/>
<EmptySpace type="unrelated" max="-2" attributes="0"/>
<Component id="dateToTextField" min="-2" pref="92" max="-2" attributes="0"/>
<EmptySpace min="-2" pref="0" max="-2" attributes="0"/>
<Component id="dateToButtonCalendar" min="-2" max="-2" attributes="0"/>
</Group>
<Group type="102" alignment="0" attributes="0">
<EmptySpace min="21" pref="21" max="21" attributes="0"/>
<Group type="103" groupAlignment="0" attributes="0">
<Group type="102" alignment="0" attributes="0">
<Group type="103" groupAlignment="0" 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>
<Group type="103" groupAlignment="0" max="-2" attributes="0">
<Group type="102" attributes="0">
<Component id="dateCheckBox" min="-2" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Component id="dateFromTextField" min="-2" pref="92" max="-2" attributes="0"/>
<EmptySpace min="-2" pref="0" max="-2" attributes="0"/>
<Component id="dateFromButtonCalendar" min="-2" max="-2" attributes="0"/>
<EmptySpace type="unrelated" min="-2" max="-2" attributes="0"/>
<Component id="jLabel1" min="-2" max="-2" attributes="0"/>
<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>
<Component id="dateToTextField" min="-2" pref="92" max="-2" attributes="0"/>
<EmptySpace min="-2" pref="0" max="-2" attributes="0"/>
<Component id="dateToButtonCalendar" min="-2" max="-2" attributes="0"/>
</Group>
<Group type="102" alignment="1" attributes="0">
<EmptySpace max="-2" attributes="0"/>
<Component id="jLabel2" min="-2" max="-2" attributes="0"/>
<EmptySpace max="32767" attributes="0"/>
<Component id="jLabel3" min="-2" max="-2" attributes="0"/>
</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">
<Component id="jLabel4" min="-2" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Component id="timeZoneComboBox" min="-2" pref="193" max="-2" attributes="0"/>
</Group>
<Group type="102" alignment="0" attributes="0">
<EmptySpace min="21" pref="21" max="21" attributes="0"/>
<Group type="103" groupAlignment="0" attributes="0">
<Component id="jLabel3" alignment="0" min="-2" max="-2" attributes="0"/>
<Component id="jLabel2" alignment="0" min="-2" max="-2" attributes="0"/>
</Group>
<Component id="modifiedCheckBox" min="-2" max="-2" attributes="0"/>
<EmptySpace min="-2" pref="6" max="-2" attributes="0"/>
<Component id="accessedCheckBox" min="-2" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<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>
<EmptySpace min="-2" pref="33" max="-2" attributes="0"/>
</Group>
</Group>
</DimensionLayout>
<DimensionLayout dim="1">
<Group type="103" groupAlignment="0" attributes="0">
<Group type="102" alignment="0" attributes="0">
<Group type="103" groupAlignment="0" attributes="0">
<Group type="103" groupAlignment="3" attributes="0">
<Component id="dateCheckBox" alignment="3" min="-2" max="-2" attributes="0"/>
<Component id="dateFromTextField" alignment="3" min="-2" max="-2" 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">
<Component id="dateCheckBox" alignment="3" min="-2" max="-2" attributes="0"/>
<Component id="dateFromTextField" alignment="3" min="-2" max="-2" attributes="0"/>
</Group>
<EmptySpace min="-2" pref="18" max="-2" attributes="0"/>
</Group>
<Component id="dateToButtonCalendar" alignment="0" min="-2" max="-2" attributes="0"/>
<Group type="103" alignment="0" groupAlignment="3" attributes="0">
<Component id="jLabel1" alignment="3" min="-2" max="-2" attributes="0"/>
<Component id="dateToTextField" alignment="3" min="-2" max="-2" attributes="0"/>
<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"/>
<Group type="103" alignment="0" groupAlignment="3" attributes="0">
<Component id="jLabel1" alignment="3" min="-2" max="-2" attributes="0"/>
<Component id="dateToTextField" alignment="3" min="-2" max="-2" attributes="0"/>
</Group>
<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>
<Component id="dateFromButtonCalendar" min="-2" max="-2" attributes="0"/>
</Group>
<EmptySpace min="-2" pref="4" max="-2" attributes="0"/>
<Group type="103" groupAlignment="3" attributes="0">
<Component id="jLabel4" alignment="3" min="-2" max="-2" attributes="0"/>
<Component id="timeZoneComboBox" alignment="3" min="-2" max="-2" attributes="0"/>
</Group>
<EmptySpace type="unrelated" max="-2" attributes="0"/>
<Group type="103" groupAlignment="1" attributes="0">
<Group type="102" alignment="1" attributes="0">
<Component id="modifiedCheckBox" min="-2" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Component id="changedCheckBox" min="-2" max="-2" attributes="0"/>
<Group type="103" groupAlignment="0" attributes="0">
<Component id="modifiedCheckBox" alignment="1" min="-2" max="-2" attributes="0"/>
<Group type="103" alignment="1" groupAlignment="3" attributes="0">
<Component id="accessedCheckBox" alignment="3" 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 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>
<Component id="createdCheckBox" alignment="1" min="-2" 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"/>
<EmptySpace min="0" pref="0" max="-2" attributes="0"/>
</Group>
</Group>
</DimensionLayout>
@ -188,6 +195,9 @@
</Component>
<Component class="javax.swing.JLabel" name="jLabel3">
<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="DateSearchPanel.jLabel3.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
@ -208,6 +218,9 @@
</Component>
<Component class="javax.swing.JLabel" name="jLabel2">
<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="DateSearchPanel.jLabel2.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>

View File

@ -74,7 +74,6 @@ class DateSearchPanel extends javax.swing.JPanel {
copyMenuItem.addActionListener(actList);
pasteMenuItem.addActionListener(actList);
selectAllMenuItem.addActionListener(actList);
}
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
jLabel3.setFont(new java.awt.Font("Tahoma", 0, 10)); // 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
@ -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
modifiedCheckBox.setSelected(true);
@ -214,69 +215,74 @@ class DateSearchPanel extends javax.swing.JPanel {
layout.setHorizontalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup()
.addComponent(dateCheckBox)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(dateFromTextField, javax.swing.GroupLayout.PREFERRED_SIZE, 92, javax.swing.GroupLayout.PREFERRED_SIZE)
.addGap(0, 0, 0)
.addComponent(dateFromButtonCalendar, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
.addComponent(jLabel1)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
.addComponent(dateToTextField, javax.swing.GroupLayout.PREFERRED_SIZE, 92, javax.swing.GroupLayout.PREFERRED_SIZE)
.addGap(0, 0, 0)
.addComponent(dateToButtonCalendar, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
.addGroup(layout.createSequentialGroup()
.addGap(21, 21, 21)
.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.LEADING)
.addComponent(changedCheckBox)
.addComponent(modifiedCheckBox))
.addComponent(dateCheckBox)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(dateFromTextField, javax.swing.GroupLayout.PREFERRED_SIZE, 92, javax.swing.GroupLayout.PREFERRED_SIZE)
.addGap(0, 0, 0)
.addComponent(dateFromButtonCalendar, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(accessedCheckBox)
.addComponent(createdCheckBox)))
.addComponent(jLabel1)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
.addComponent(dateToTextField, javax.swing.GroupLayout.PREFERRED_SIZE, 92, javax.swing.GroupLayout.PREFERRED_SIZE)
.addGap(0, 0, 0)
.addComponent(dateToButtonCalendar, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
.addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
.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.createSequentialGroup()
.addComponent(jLabel4)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(timeZoneComboBox, javax.swing.GroupLayout.PREFERRED_SIZE, 193, javax.swing.GroupLayout.PREFERRED_SIZE))
.addGroup(layout.createSequentialGroup()
.addGap(21, 21, 21)
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(jLabel3)
.addComponent(jLabel2)))))
.addComponent(modifiedCheckBox)
.addGap(6, 6, 6)
.addComponent(accessedCheckBox)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(createdCheckBox)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(changedCheckBox)))
.addGap(33, 33, 33))
);
layout.setVerticalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup()
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
.addComponent(dateCheckBox)
.addComponent(dateFromTextField, 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)
.addComponent(jLabel1)
.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))
.addGap(4, 4, 4)
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false)
.addGroup(layout.createSequentialGroup()
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
.addComponent(dateCheckBox)
.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)
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
.addComponent(jLabel1)
.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))
.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)
.addComponent(jLabel4)
.addComponent(timeZoneComboBox, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING)
.addGroup(layout.createSequentialGroup()
.addComponent(modifiedCheckBox)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(changedCheckBox))
.addGroup(layout.createSequentialGroup()
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(modifiedCheckBox, javax.swing.GroupLayout.Alignment.TRAILING)
.addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
.addComponent(accessedCheckBox)
.addGap(23, 23, 23))
.addComponent(createdCheckBox))
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
.addComponent(jLabel2)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(jLabel3)
.addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
.addComponent(createdCheckBox)
.addComponent(changedCheckBox)))
.addGap(0, 0, 0))
);
}// </editor-fold>//GEN-END:initComponents

View File

@ -1,6 +1,11 @@
<?xml version="1.0" encoding="UTF-8" ?>
<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>
<AuxValue name="FormSettings_autoResourcing" type="java.lang.Integer" value="1"/>
<AuxValue name="FormSettings_autoSetComponentName" type="java.lang.Boolean" value="false"/>
@ -16,13 +21,48 @@
<Layout>
<DimensionLayout dim="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>
</DimensionLayout>
<DimensionLayout dim="1">
<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>
</DimensionLayout>
</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>

View File

@ -60,8 +60,7 @@ import org.sleuthkit.datamodel.TskCoreException;
*/
class FileSearchPanel extends javax.swing.JPanel {
private List<FilterArea> filterAreas = new ArrayList<FilterArea>();
private JButton searchButton;
private final List<FilterArea> filterAreas = new ArrayList<>();
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");
@ -79,14 +78,6 @@ class FileSearchPanel extends javax.swing.JPanel {
*/
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"));
label.setAlignmentX(Component.LEFT_ALIGNMENT);
label.setBorder(new EmptyBorder(0, 0, 10, 0));
@ -95,8 +86,9 @@ class FileSearchPanel extends javax.swing.JPanel {
// Create and add filter areas
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 MimeTypeFilter());
metadataFilters.add(new DateSearchFilter());
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);
}
// 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() {
@Override
public void actionPerformed(ActionEvent e) {
@ -234,7 +221,7 @@ class FileSearchPanel extends javax.swing.JPanel {
}
private Collection<FileSearchFilter> getFilters() {
Collection<FileSearchFilter> filters = new ArrayList<FileSearchFilter>();
Collection<FileSearchFilter> filters = new ArrayList<>();
for (FilterArea fa : this.filterAreas) {
filters.addAll(fa.getFilters());
@ -244,7 +231,7 @@ class FileSearchPanel extends javax.swing.JPanel {
}
private Collection<FileSearchFilter> getEnabledFilters() {
Collection<FileSearchFilter> enabledFilters = new ArrayList<FileSearchFilter>();
Collection<FileSearchFilter> enabledFilters = new ArrayList<>();
for (FileSearchFilter f : this.getFilters()) {
if (f.isEnabled()) {
@ -273,17 +260,38 @@ class FileSearchPanel extends javax.swing.JPanel {
// <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN: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);
this.setLayout(layout);
layout.setHorizontalGroup(
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.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
// 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
}

View File

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

View File

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

View File

@ -89,24 +89,27 @@ class KnownStatusSearchPanel extends javax.swing.JPanel {
this.setLayout(layout);
layout.setHorizontalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(knownCheckBox)
.addGroup(layout.createSequentialGroup()
.addGap(21, 21, 21)
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(knownBadOptionCheckBox)
.addComponent(unknownOptionCheckBox)
.addComponent(knownOptionCheckBox)))
.addComponent(knownCheckBox)
.addGroup(layout.createSequentialGroup()
.addGap(21, 21, 21)
.addComponent(unknownOptionCheckBox)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(knownOptionCheckBox)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(knownBadOptionCheckBox)))
.addContainerGap(28, Short.MAX_VALUE))
);
layout.setVerticalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup()
.addComponent(knownCheckBox)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
.addComponent(unknownOptionCheckBox)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(knownOptionCheckBox)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(knownBadOptionCheckBox))
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
.addComponent(unknownOptionCheckBox)
.addComponent(knownOptionCheckBox)
.addComponent(knownBadOptionCheckBox)))
);
}// </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">
<Group type="103" groupAlignment="0" attributes="0">
<Group type="102" alignment="0" attributes="0">
<Component id="nameCheckBox" min="-2" max="-2" attributes="0"/>
<Group type="103" groupAlignment="0" max="-2" attributes="0">
<EmptySpace min="0" pref="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">
<EmptySpace min="-2" pref="12" max="-2" attributes="0"/>
<Component id="noteNameLabel" min="-2" max="-2" attributes="0"/>
<Component id="nameCheckBox" min="-2" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
</Group>
<Group type="102" attributes="1">
<EmptySpace max="-2" attributes="0"/>
<Component id="searchTextField" max="32767" attributes="0"/>
<Component id="searchTextField" min="-2" pref="247" max="-2" attributes="0"/>
</Group>
</Group>
<EmptySpace min="0" pref="0" max="-2" attributes="0"/>
</Group>
</Group>
</DimensionLayout>
@ -79,6 +77,7 @@
</Group>
<EmptySpace max="-2" attributes="0"/>
<Component id="noteNameLabel" min="-2" max="-2" attributes="0"/>
<EmptySpace min="0" pref="0" max="32767" attributes="0"/>
</Group>
</Group>
</DimensionLayout>
@ -121,6 +120,15 @@
<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;)"/>
</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>
</Component>
</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.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);
this.setLayout(layout);
layout.setHorizontalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup()
.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())
.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()
.addComponent(nameCheckBox)
.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.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
@ -144,7 +146,8 @@ class NameSearchPanel extends javax.swing.JPanel {
.addComponent(nameCheckBox)
.addComponent(searchTextField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
.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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -1,7 +1,7 @@
/*
* Autopsy Forensic Browser
*
* Copyright 2015 Basis Technology Corp.
* Copyright 2011-2016 Basis Technology Corp.
* Contact: carrier <at> sleuthkit <dot> org
*
* Licensed under the Apache License, Version 2.0 (the "License");
@ -45,8 +45,8 @@ public final class ContentChangedEvent extends AutopsyEvent implements Serializa
* 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.
*
* @param contentEvent A ModuleContentEvent object containing the data
* associated with the content addition or change.
* @param eventData A ModuleContentEvent object containing the data
* associated with the content addition or change.
*/
public ContentChangedEvent(ModuleContentEvent eventData) {
/**

View File

@ -43,7 +43,6 @@ FileExtMismatchSettingsPanel.mimeRemoveErrLabel.text=\
FileExtMismatchSettingsPanel.extRemoveErrLabel.text=\
FileExtMismatchSettingsPanel.mimeErrLabel.text=\
FileExtMismatchSettingsPanel.removeTypeButton.text=Remove Selected Type
FileExtMismatchSettingsPanel.saveButton.text=Save Configuration
FileExtMismatchSettingsPanel.jLabel1.text=File Types:
FileExtMismatchSettingsPanel.userExtTextField.text=
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.extHeaderLabel.text=\u8a31\u53ef\u3059\u308b\u62e1\u5f35\u5b50\uff1a
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.addExtButton.text=\u62e1\u5f35\u5b50\u3092\u8ffd\u52a0
FileExtMismatchSettingsPanel.removeExtButton.text=\u9078\u629e\u3057\u305f\u62e1\u5f35\u5b50\u3092\u524a\u9664

View File

@ -46,13 +46,10 @@
<Group type="102" attributes="0">
<EmptySpace max="-2" 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">
<EmptySpace min="0" pref="0" max="32767" attributes="0"/>
<Group type="103" groupAlignment="0" 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>
<Component id="saveMsgLabel" min="-2" pref="145" max="-2" attributes="0"/>
</Group>
</Group>
<EmptySpace max="-2" attributes="0"/>
@ -63,9 +60,7 @@
<Group type="103" groupAlignment="0" attributes="0">
<Group type="102" attributes="0">
<EmptySpace max="-2" attributes="0"/>
<Component id="jSplitPane1" min="-2" max="-2" attributes="0"/>
<EmptySpace type="unrelated" max="-2" attributes="0"/>
<Component id="saveButton" min="-2" max="-2" attributes="0"/>
<Component id="jSplitPane1" min="-2" pref="466" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Component id="saveMsgLabel" min="-2" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
@ -74,20 +69,6 @@
</DimensionLayout>
</Layout>
<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">
<Properties>
<Property name="dividerLocation" type="int" value="430"/>
@ -146,7 +127,7 @@
<Component id="removeTypeButton" min="-2" max="-2" attributes="0"/>
<EmptySpace 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>
</DimensionLayout>

View File

@ -69,7 +69,7 @@ final class FileExtMismatchSettingsPanel extends IngestModuleGlobalSettingsPanel
customizeComponents();
}
@NbBundle.Messages({"FileExtMismatchSettingsPanel.Title=Global File Extension Mismatch Identification Settings"})
@NbBundle.Messages({"FileExtMismatchSettingsPanel.Title=Global File Extension Mismatch Identification Settings"})
private void customizeComponents() {
setName(Bundle.FileExtMismatchSettingsPanel_Title());
@ -143,7 +143,6 @@ final class FileExtMismatchSettingsPanel extends IngestModuleGlobalSettingsPanel
jScrollPane1 = new javax.swing.JScrollPane();
jPanel1 = new javax.swing.JPanel();
saveButton = new javax.swing.JButton();
jSplitPane1 = new javax.swing.JSplitPane();
mimePanel = new javax.swing.JPanel();
jLabel1 = new javax.swing.JLabel();
@ -167,15 +166,6 @@ final class FileExtMismatchSettingsPanel extends IngestModuleGlobalSettingsPanel
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);
jLabel1.setText(org.openide.util.NbBundle.getMessage(FileExtMismatchSettingsPanel.class, "FileExtMismatchSettingsPanel.jLabel1.text")); // NOI18N
@ -247,7 +237,7 @@ final class FileExtMismatchSettingsPanel extends IngestModuleGlobalSettingsPanel
.addComponent(removeTypeButton)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(mimeRemoveErrLabel)
.addContainerGap(47, Short.MAX_VALUE))
.addContainerGap(83, Short.MAX_VALUE))
);
jSplitPane1.setLeftComponent(mimePanel);
@ -336,21 +326,17 @@ final class FileExtMismatchSettingsPanel extends IngestModuleGlobalSettingsPanel
.addGroup(jPanel1Layout.createSequentialGroup()
.addContainerGap()
.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()
.addGap(0, 0, Short.MAX_VALUE)
.addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.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))))
.addComponent(saveMsgLabel, javax.swing.GroupLayout.PREFERRED_SIZE, 145, javax.swing.GroupLayout.PREFERRED_SIZE)))
.addContainerGap())
);
jPanel1Layout.setVerticalGroup(
jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(jPanel1Layout.createSequentialGroup()
.addContainerGap()
.addComponent(jSplitPane1, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
.addComponent(saveButton)
.addComponent(jSplitPane1, javax.swing.GroupLayout.PREFERRED_SIZE, 466, javax.swing.GroupLayout.PREFERRED_SIZE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(saveMsgLabel)
.addContainerGap())
@ -416,10 +402,6 @@ final class FileExtMismatchSettingsPanel extends IngestModuleGlobalSettingsPanel
setIsModified();
}//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
String newMime = userTypeTextField.getText();
if (newMime.isEmpty()) {
@ -555,7 +537,6 @@ final class FileExtMismatchSettingsPanel extends IngestModuleGlobalSettingsPanel
extErrorLabel.setText(" ");
saveMsgLabel.setText(NbBundle.getMessage(this.getClass(), "FileExtMismatchConfigPanel.store.msg"));
saveButton.setEnabled(false);
} else {
//error
JOptionPane.showMessageDialog(this,
@ -582,7 +563,6 @@ final class FileExtMismatchSettingsPanel extends IngestModuleGlobalSettingsPanel
}
private void setIsModified() {
saveButton.setEnabled(true);
saveMsgLabel.setText(" ");
}
@ -592,18 +572,7 @@ final class FileExtMismatchSettingsPanel extends IngestModuleGlobalSettingsPanel
}
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();
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.JButton removeExtButton;
private javax.swing.JButton removeTypeButton;
private javax.swing.JButton saveButton;
private javax.swing.JLabel saveMsgLabel;
private javax.swing.JTextField userExtTextField;
private javax.swing.JTextField userTypeTextField;

View File

@ -18,6 +18,7 @@
*/
package org.sleuthkit.autopsy.modules.filetypeid;
import java.io.Serializable;
import java.nio.charset.StandardCharsets;
import java.util.Arrays;
import java.util.Objects;
@ -31,8 +32,9 @@ import org.sleuthkit.datamodel.TskCoreException;
* <p>
* Thread-safe (immutable).
*/
class FileType {
class FileType implements Serializable {
private static final long serialVersionUID = 1L;
private final String mimeType;
private final Signature signature;
private final String interestingFilesSetName;
@ -104,19 +106,20 @@ class FileType {
String getFilesSetName() {
return interestingFilesSetName;
}
@Override
public String toString() {
return this.mimeType;
}
@Override
public boolean equals(Object other) {
if(other != null && other instanceof FileType) {
if (other != null && other instanceof FileType) {
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 false;
}
@ -134,14 +137,16 @@ class FileType {
* <p>
* 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());
/**
* The way the signature byte sequence should be interpreted.
*/
enum Type {
RAW, ASCII
};
@ -156,8 +161,8 @@ class FileType {
*
* @param signatureBytes The signature bytes.
* @param offset The offset of the signature bytes.
* @param type The type of data in the byte array. Impacts
* how it is displayed to the user in the UI.
* @param type The type of data in the byte array. Impacts how
* it is displayed to the user in the UI.
*/
Signature(final byte[] signatureBytes, long offset, Type type) {
this.signatureBytes = Arrays.copyOf(signatureBytes, signatureBytes.length);
@ -165,13 +170,13 @@ class FileType {
this.type = type;
this.isRelativeToStart = true;
}
/**
* Creates a file signature consisting of an ASCII string at a
* specific offset within a file.
* Creates a file signature consisting of an ASCII string at a specific
* offset within a file.
*
* @param signatureString The ASCII string
* @param offset The offset of the signature bytes.
* @param offset The offset of the signature bytes.
*/
Signature(String signatureString, long offset) {
this.signatureBytes = signatureString.getBytes(StandardCharsets.US_ASCII);
@ -179,12 +184,12 @@ class FileType {
this.type = Type.ASCII;
this.isRelativeToStart = true;
}
/**
* Creates a file signature consisting of a sequence of bytes at a
* specific offset within a file. If bytes correspond to an ASCII
* string, use one of the other constructors so that the string is
* displayed to the user instead of the raw bytes.
* specific offset within a file. If bytes correspond to an ASCII
* string, use one of the other constructors so that the string is
* displayed to the user instead of the raw bytes.
*
* @param signatureBytes The signature bytes.
* @param offset The offset of the signature bytes.
@ -195,16 +200,17 @@ class FileType {
this.type = Type.RAW;
this.isRelativeToStart = true;
}
/**
* Creates a file signature consisting of a sequence of bytes at a
* specific offset within a file.
*
* @param signatureBytes The signature bytes.
* @param offset The offset of the signature bytes.
* @param type The type of data in the byte array. Impacts
* how it is displayed to the user in the UI.
* @param isRelativeToStart Determines whether this signature is relative to start.
* @param signatureBytes The signature bytes.
* @param offset The offset of the signature bytes.
* @param type The type of data in the byte array. Impacts
* how it is displayed to the user in the UI.
* @param isRelativeToStart Determines whether this signature is
* relative to start.
*/
Signature(final byte[] signatureBytes, long offset, Type type, boolean isRelativeToStart) {
this.signatureBytes = Arrays.copyOf(signatureBytes, signatureBytes.length);
@ -212,14 +218,15 @@ class FileType {
this.type = type;
this.isRelativeToStart = isRelativeToStart;
}
/**
* Creates a file signature consisting of an ASCII string at a
* specific offset within a file.
* Creates a file signature consisting of an ASCII string at a specific
* offset within a file.
*
* @param signatureString The ASCII string
* @param offset The offset of the signature bytes.
* @param isRelativeToStart Determines whether this signature is relative to start.
* @param signatureString The ASCII string
* @param offset The offset of the signature bytes.
* @param isRelativeToStart Determines whether this signature is
* relative to start.
*/
Signature(String signatureString, long offset, boolean isRelativeToStart) {
this.signatureBytes = signatureString.getBytes(StandardCharsets.US_ASCII);
@ -227,16 +234,17 @@ class FileType {
this.type = Type.ASCII;
this.isRelativeToStart = isRelativeToStart;
}
/**
* Creates a file signature consisting of a sequence of bytes at a
* specific offset within a file. If bytes correspond to an ASCII
* string, use one of the other constructors so that the string is
* displayed to the user instead of the raw bytes.
* specific offset within a file. If bytes correspond to an ASCII
* string, use one of the other constructors so that the string is
* displayed to the user instead of the raw bytes.
*
* @param signatureBytes The signature bytes.
* @param offset The offset of the signature bytes.
* @param isRelativeToStart Determines whether this signature is relative to start.
* @param signatureBytes The signature bytes.
* @param offset The offset of the signature bytes.
* @param isRelativeToStart Determines whether this signature is
* relative to start.
*/
Signature(final byte[] signatureBytes, long offset, boolean isRelativeToStart) {
this.signatureBytes = Arrays.copyOf(signatureBytes, signatureBytes.length);
@ -271,7 +279,7 @@ class FileType {
Type getType() {
return type;
}
boolean isRelativeToStart() {
return isRelativeToStart;
}
@ -285,12 +293,13 @@ class FileType {
* @return True or false.
*/
boolean containedIn(final AbstractFile file) {
if(offset >= file.getSize()) {
if (offset >= file.getSize()) {
return false; // File is too small, offset lies outside file.
}
long actualOffset = offset;
if(!isRelativeToStart)
if (!isRelativeToStart) {
actualOffset = file.getSize() - 1 - offset;
}
if (file.getSize() < (actualOffset + signatureBytes.length)) {
return false; /// too small, can't contain this signature
}
@ -308,15 +317,16 @@ class FileType {
return false;
}
}
@Override
public boolean equals(Object other) {
if (other != null && other instanceof Signature) {
Signature that = (Signature) other;
if(Arrays.equals(this.getSignatureBytes(), that.getSignatureBytes())
if (Arrays.equals(this.getSignatureBytes(), that.getSignatureBytes())
&& this.getOffset() == that.getOffset()
&& this.getType().equals(that.getType()))
&& this.getType().equals(that.getType())) {
return true;
}
}
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
* 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
* FileTypeDetector.detect, if AbstractFile.getMIMEType returns null.
*
* @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
* writing the result to the case database.
*/
@SuppressWarnings("deprecation")
public String getFileType(AbstractFile file) throws TskCoreException {
String mimeType = file.getMIMEType();
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;
return detect(file, true);
}
/**
@ -186,9 +158,39 @@ public class FileTypeDetector {
* @return A MIME type name. If file type could not be detected or results
* 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 {
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),
* 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.UNUSED_BLOCKS)
|| (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.
*/
if (null == mimeType) {
mimeType = detectUserDefinedType(file, addToCaseDb);
}
/*
* If the file does not match a user-defined type, send the initial
* bytes to Tika.
*/
String mimeType = detectUserDefinedType(file);
if (null == mimeType) {
/*
* The file does not match a user-defined type. Send the initial
* bytes to Tika.
*/
try {
byte buf[];
int len = file.read(buffer, 0, BUFFER_SIZE);
@ -237,25 +242,63 @@ public class FileTypeDetector {
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;
}
/**
* 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
* calls for an alert on a match, an interesting file hit artifact is posted
* to the blackboard.
* predefined file type. If postToBlackBoard is true, and a match is found,
* and the file type definition calls for an alert on a match, an
* 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.
*
* @throws TskCoreException
*/
private String detectUserDefinedType(AbstractFile file) throws TskCoreException {
private String detectUserDefinedType(AbstractFile file, boolean postToBlackBoard) throws TskCoreException {
for (FileType fileType : userDefinedFileTypes) {
if (fileType.matches(file)) {
if (fileType.alertOnMatch()) {
if (postToBlackBoard && fileType.alertOnMatch()) {
/*
* Create an interesting file hit artifact.
*/

View File

@ -19,7 +19,9 @@
package org.sleuthkit.autopsy.modules.filetypeid;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.nio.file.Path;
@ -27,6 +29,7 @@ import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.List;
import java.util.logging.Level;
import javax.persistence.PersistenceException;
import javax.xml.parsers.ParserConfigurationException;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
@ -34,10 +37,13 @@ import org.w3c.dom.NodeList;
import javax.xml.bind.DatatypeConverter;
import javax.xml.transform.TransformerException;
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.PlatformUtil;
import org.sleuthkit.autopsy.coreutils.XMLUtil;
import org.sleuthkit.autopsy.modules.filetypeid.FileType.Signature;
import org.sleuthkit.datamodel.TskCoreException;
import org.w3c.dom.Node;
import org.xml.sax.SAXException;
@ -59,7 +65,8 @@ import org.xml.sax.SAXException;
final class UserDefinedFileTypesManager {
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_TYPE_TAG_NAME = "FileType"; //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 {
try {
String filePath = getFileTypeDefinitionsFilePath(USER_DEFINED_TYPE_DEFINITIONS_FILE);
File file = new File(filePath);
if (file.exists() && file.canRead()) {
for (FileType fileType : XmlReader.readFileTypes(filePath)) {
File serialized = new File(getFileTypeDefinitionsFilePath(USER_DEFINED_TYPES_SERIALIZATION_FILE));
if (serialized.exists()) {
for (FileType fileType : readFileTypesSerialized()) {
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) {
@ -282,14 +296,8 @@ final class UserDefinedFileTypesManager {
* types.
*/
synchronized void setUserDefinedFileTypes(List<FileType> newFileTypes) throws UserDefinedFileTypesException {
try {
String filePath = getFileTypeDefinitionsFilePath(USER_DEFINED_TYPE_DEFINITIONS_FILE);
XmlWriter.writeFileTypes(newFileTypes, filePath);
} catch (ParserConfigurationException | FileNotFoundException | UnsupportedEncodingException | TransformerException ex) {
throwUserDefinedFileTypesException(ex, "UserDefinedFileTypesManager.saveFileTypes.errorMessage");
} catch (IOException ex) {
throwUserDefinedFileTypesException(ex, "UserDefinedFileTypesManager.saveFileTypes.errorMessage");
}
String filePath = getFileTypeDefinitionsFilePath(USER_DEFINED_TYPES_SERIALIZATION_FILE);
writeFileTypes(newFileTypes, filePath);
}
/**
@ -305,127 +313,52 @@ final class UserDefinedFileTypesManager {
}
/**
* Provides a mechanism for writing a set of file type definitions to an XML
* file.
* Writes a set of file types to a file.
*
* @param fileTypes A collection of file types.
* @param filePath The path to the destination file.
*
* @throws ParserConfigurationException
* @throws IOException
* @throws FileNotFoundException
* @throws UnsupportedEncodingException
* @throws TransformerException
*/
private static class XmlWriter {
private static void writeFileTypes(List<FileType> fileTypes, String filePath) throws UserDefinedFileTypesException {
try (NbObjectOutputStream out = new NbObjectOutputStream(new FileOutputStream(filePath))) {
UserDefinedFileTypesSettings settings = new UserDefinedFileTypesSettings(fileTypes);
out.writeObject(settings);
} catch (IOException ex) {
throw new UserDefinedFileTypesException(String.format("Failed to write settings to %s", filePath), ex);
}
}
/**
* Writes a set of file type definitions to an XML file.
*
* @param fileTypes A collection of file types.
* @param filePath The path to the destination file.
*
* @throws ParserConfigurationException
* @throws IOException
* @throws FileNotFoundException
* @throws UnsupportedEncodingException
* @throws TransformerException
*/
private static void writeFileTypes(List<FileType> fileTypes, String filePath) throws ParserConfigurationException, IOException, FileNotFoundException, UnsupportedEncodingException, TransformerException {
Document doc = XMLUtil.createDocument();
Element fileTypesElem = doc.createElement(FILE_TYPES_TAG_NAME);
doc.appendChild(fileTypesElem);
for (FileType fileType : fileTypes) {
Element fileTypeElem = XmlWriter.createFileTypeElement(fileType, doc);
fileTypesElem.appendChild(fileTypeElem);
/**
* Reads the file types
*
* @param filePath the file path where the file types are to be read
*
* @return the file types
*
* @throws ParserConfigurationException If the file cannot be read
*/
private static List<FileType> readFileTypesSerialized() throws UserDefinedFileTypesException {
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();
}
XMLUtil.saveDocument(doc, ENCODING_FOR_XML_FILE, filePath);
} catch (IOException | ClassNotFoundException ex) {
throw new UserDefinedFileTypesException("Couldn't read serialized settings.", ex);
}
/**
* 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.
*
* @param fileType The file type to use as a content source.
* @param fileTypeElem The parent file type element.
*/
private static void addAlertAttribute(FileType fileType, Element fileTypeElem) {
fileTypeElem.setAttribute(ALERT_ATTRIBUTE, Boolean.toString(fileType.alertOnMatch()));
}
/**
* 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
* XML file.
*/
private static class XmlReader {
private static class XMLDefinitionsReader {
/**
* 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.
*/
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<>();
/*
* RC: Commenting out the loadDocument overload that validates
@ -453,7 +386,7 @@ final class UserDefinedFileTypesManager {
NodeList fileTypeElems = fileTypesElem.getElementsByTagName(FILE_TYPE_TAG_NAME);
for (int i = 0; i < fileTypeElems.getLength(); ++i) {
Element fileTypeElem = (Element) fileTypeElems.item(i);
FileType fileType = XmlReader.parseFileType(fileTypeElem);
FileType fileType = XMLDefinitionsReader.parseFileType(fileTypeElem);
fileTypes.add(fileType);
}
}
@ -472,10 +405,10 @@ final class UserDefinedFileTypesManager {
* @throws NumberFormatException
*/
private static FileType parseFileType(Element fileTypeElem) throws IllegalArgumentException, NumberFormatException {
String mimeType = XmlReader.parseMimeType(fileTypeElem);
Signature signature = XmlReader.parseSignature(fileTypeElem);
String filesSetName = XmlReader.parseInterestingFilesSet(fileTypeElem);
boolean alert = XmlReader.parseAlert(fileTypeElem);
String mimeType = XMLDefinitionsReader.parseMimeType(fileTypeElem);
Signature signature = XMLDefinitionsReader.parseSignature(fileTypeElem);
String filesSetName = XMLDefinitionsReader.parseInterestingFilesSet(fileTypeElem);
boolean alert = XMLDefinitionsReader.parseAlert(fileTypeElem);
return new FileType(mimeType, signature, filesSetName, alert);
}
@ -573,7 +506,7 @@ final class UserDefinedFileTypesManager {
* Private constructor suppresses creation of instanmces of this utility
* 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
ReportProgressPanel.reportLabel.text=reportLabel
ReportProgressPanel.pathLabel.text=pathLabel
ReportProgressPanel.separationLabel.text=-
ReportProgressPanel.processingLabel.text=processingLabel
ReportProgressPanel.separationLabel.text=:
ReportProgressPanel.statusMessageLabel.text=processingLabel
ReportGenerationPanel.titleLabel.text=Report Generation Progress
ReportVisualPanel2.taggedResultsRadioButton.text=Tagged Results
ReportVisualPanel2.allResultsRadioButton.text=All Results

View File

@ -1,247 +1,246 @@
OpenIDE-Module-Name=\u30EC\u30DD\u30FC\u30C8
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
OpenIDE-Module-Name=\u30ec\u30dd\u30fc\u30c8
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.okButton.text=OK
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
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.selectAllButton.text=\u5168\u3066\u9078\u629E
ReportVisualPanel2.advancedButton.text=\u30C7\u30FC\u30BF\u30BF\u30A4\u30D7
ArtifactSelectionDialog.deselectAllButton.text=\u5168\u3066\u9078\u629E\u89E3\u9664
ArtifactSelectionDialog.selectAllButton.text=\u5168\u3066\u9078\u629E
ReportGenerationPanel.closeButton.text=\u9589\u3058\u308B
ReportProgressPanel.reportLabel.text=\u30EC\u30DD\u30FC\u30C8\u30E9\u30D9\u30EB
ReportProgressPanel.pathLabel.text=\u30D1\u30B9\u30E9\u30D9\u30EB
ReportProgressPanel.separationLabel.text=-
ReportProgressPanel.processingLabel.text=\u30D7\u30ED\u30BB\u30B7\u30F3\u30B0\u30E9\u30D9\u30EB
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.allResultsRadioButton.text=\u5168\u3066\u306E\u7D50\u679C
ReportWizardFileOptionsVisualPanel.selectAllButton.text=\u5168\u3066\u9078\u629E
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
ArtifactSelectionDialog.dlgTitle.text=\u30A2\u30C9\u30D0\u30F3\u30B9\u30A2\u30FC\u30C6\u30A3\u30D5\u30A1\u30AF\u30C8\u9078\u629E
FileReportDataTypes.filename.text=\u540D\u524D
FileReportDataTypes.fileExt.text=\u30D5\u30A1\u30A4\u30EB\u62E1\u5F35\u5B50
FileReportDataTypes.fileType.text=\u30D5\u30A1\u30A4\u30EB\u30BF\u30A4\u30D7
FileReportDataTypes.isDel.text=\u306F\u524A\u9664\u3055\u308C\u307E\u3057\u305F
FileReportDataTypes.aTime.text=\u6700\u5F8C\u306E\u30A2\u30AF\u30BB\u30B9
FileReportDataTypes.crTime.text=\u4F5C\u6210\u3055\u308C\u305F\u30D5\u30A1\u30A4\u30EB
FileReportDataTypes.mTime.text=\u6700\u5F8C\u306E\u4FEE\u6B63
FileReportDataTypes.size.text=\u30B5\u30A4\u30BA
FileReportDataTypes.address.text=\u30A2\u30C9\u30EC\u30B9
FileReportDataTypes.hash.text=\u30CF\u30C3\u30B7\u30E5\u5024
FileReportDataTypes.knownStatus.text=\u65E2\u77E5\u30B9\u30C6\u30FC\u30BF\u30B9
FileReportDataTypes.perms.text=\u30D1\u30FC\u30DF\u30C3\u30B7\u30E7\u30F3
FileReportDataTypes.path.text=\u30D5\u30EB\u30D1\u30B9
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
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.progress.loading=\u30D5\u30A1\u30A4\u30EB\u306E\u8AAD\u307F\u8FBC\u307F\u4E2D\u2026
ReportBodyFile.progress.processing={0}\u3092\u51E6\u7406\u4E2D\u2026
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
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
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.selectAllButton.text=\u5168\u3066\u9078\u629e
ReportVisualPanel2.advancedButton.text=\u30c7\u30fc\u30bf\u30bf\u30a4\u30d7
ArtifactSelectionDialog.deselectAllButton.text=\u5168\u3066\u9078\u629e\u89e3\u9664
ArtifactSelectionDialog.selectAllButton.text=\u5168\u3066\u9078\u629e
ReportGenerationPanel.closeButton.text=\u9589\u3058\u308b
ReportProgressPanel.reportLabel.text=\u30ec\u30dd\u30fc\u30c8\u30e9\u30d9\u30eb
ReportProgressPanel.pathLabel.text=\u30d1\u30b9\u30e9\u30d9\u30eb
ReportProgressPanel.separationLabel.text=:
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
ReportVisualPanel2.taggedResultsRadioButton.text=\u30bf\u30b0\u3055\u308c\u305f\u7d50\u679c
ReportVisualPanel2.allResultsRadioButton.text=\u5168\u3066\u306e\u7d50\u679c
ReportWizardFileOptionsVisualPanel.selectAllButton.text=\u5168\u3066\u9078\u629e
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
ArtifactSelectionDialog.dlgTitle.text=\u30a2\u30c9\u30d0\u30f3\u30b9\u30a2\u30fc\u30c6\u30a3\u30d5\u30a1\u30af\u30c8\u9078\u629e
FileReportDataTypes.filename.text=\u540d\u524d
FileReportDataTypes.fileExt.text=\u30d5\u30a1\u30a4\u30eb\u62e1\u5f35\u5b50
FileReportDataTypes.fileType.text=\u30d5\u30a1\u30a4\u30eb\u30bf\u30a4\u30d7
FileReportDataTypes.isDel.text=\u306f\u524a\u9664\u3055\u308c\u307e\u3057\u305f
FileReportDataTypes.aTime.text=\u6700\u5f8c\u306e\u30a2\u30af\u30bb\u30b9
FileReportDataTypes.crTime.text=\u4f5c\u6210\u3055\u308c\u305f\u30d5\u30a1\u30a4\u30eb
FileReportDataTypes.mTime.text=\u6700\u5f8c\u306e\u4fee\u6b63
FileReportDataTypes.size.text=\u30b5\u30a4\u30ba
FileReportDataTypes.address.text=\u30a2\u30c9\u30ec\u30b9
FileReportDataTypes.hash.text=\u30cf\u30c3\u30b7\u30e5\u5024
FileReportDataTypes.knownStatus.text=\u65e2\u77e5\u30b9\u30c6\u30fc\u30bf\u30b9
FileReportDataTypes.perms.text=\u30d1\u30fc\u30df\u30c3\u30b7\u30e7\u30f3
FileReportDataTypes.path.text=\u30d5\u30eb\u30d1\u30b9
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
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.progress.loading=\u30d5\u30a1\u30a4\u30eb\u306e\u8aad\u307f\u8fbc\u307f\u4e2d\u2026
ReportBodyFile.progress.processing={0}\u3092\u51e6\u7406\u4e2d\u2026
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.getFilePath.text=BodyFile.txt
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
ReportExcel.numAartifacts.text=\u30A2\u30FC\u30C6\u30A3\u30D5\u30A1\u30AF\u30C8\u6570\uFF1A
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.sheetName.text=\u30B5\u30DE\u30EA\u30FC
ReportExcel.cellVal.summary=\u30B5\u30DE\u30EA\u30FC
ReportExcel.cellVal.caseName=\u30B1\u30FC\u30B9\u540D\uFF1A
ReportExcel.cellVal.caseNum=\u30B1\u30FC\u30B9\u756A\u53F7\uFF1A
ReportExcel.cellVal.examiner=\u8ABF\u67FB\u62C5\u5F53\u8005\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.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.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.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.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.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.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.tagTable.header.resultType=\u7D50\u679C\u30BF\u30A4\u30D7
ReportGenerator.tagTable.header.tag=\u30BF\u30B0
ReportGenerator.tagTable.header.comment=\u30B3\u30E1\u30F3\u30C8
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.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.writeKwHits.userSrchs=\u30E6\u30FC\u30B6\u691C\u7D22
ReportGenerator.progress.processingList={0} ({1})\u3092\u51E6\u7406\u4E2D\u2026
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
ReportExcel.numAartifacts.text=\u30a2\u30fc\u30c6\u30a3\u30d5\u30a1\u30af\u30c8\u6570\uff1a
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.sheetName.text=\u30b5\u30de\u30ea\u30fc
ReportExcel.cellVal.summary=\u30b5\u30de\u30ea\u30fc
ReportExcel.cellVal.caseName=\u30b1\u30fc\u30b9\u540d\uff1a
ReportExcel.cellVal.caseNum=\u30b1\u30fc\u30b9\u756a\u53f7\uff1a
ReportExcel.cellVal.examiner=\u8abf\u67fb\u62c5\u5f53\u8005\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.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.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.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.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.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.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.tagTable.header.resultType=\u7d50\u679c\u30bf\u30a4\u30d7
ReportGenerator.tagTable.header.tag=\u30bf\u30b0
ReportGenerator.tagTable.header.comment=\u30b3\u30e1\u30f3\u30c8
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.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.writeKwHits.userSrchs=\u30e6\u30fc\u30b6\u691c\u7d22
ReportGenerator.progress.processingList={0} ({1})\u3092\u51e6\u7406\u4e2d\u2026
ReportGenerator.artTableColHdr.url=URL
ReportGenerator.artTableColHdr.title=\u30BF\u30A4\u30C8\u30EB
ReportGenerator.artTableColHdr.dateCreated=\u4F5C\u6210\u65E5\u4ED8
ReportGenerator.artTableColHdr.program=\u30D7\u30ED\u30B0\u30E9\u30E0
ReportGenerator.artTableColHdr.srcFile=\u30BD\u30FC\u30B9\u30D5\u30A1\u30A4\u30EB
ReportGenerator.artTableColHdr.dateTime=\u65E5\u4ED8\uFF0F\u6642\u523B
ReportGenerator.artTableColHdr.name=\u540D\u524D
ReportGenerator.artTableColHdr.value=\u30D0\u30EA\u30E5\u30FC
ReportGenerator.artTableColHdr.dateAccessed=\u30A2\u30AF\u30BB\u30B9\u65E5\u4ED8
ReportGenerator.artTableColHdr.referrer=\u30EA\u30D5\u30A1\u30E9
ReportGenerator.artTableColHdr.dest=\u30C7\u30B9\u30C6\u30A3\u30CD\u30FC\u30B7\u30E7\u30F3
ReportGenerator.artTableColHdr.sourceUrl=\u30BD\u30FC\u30B9URL
ReportGenerator.artTableColHdr.path=\u30D1\u30B9
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.preview=\u30D7\u30EC\u30D3\u30E5\u30FC
ReportGenerator.artTableColHdr.file=\u30D5\u30A1\u30A4\u30EB
ReportGenerator.artTableColHdr.size=\u30B5\u30A4\u30BA
ReportGenerator.artTableColHdr.deviceId=\u6A5F\u5668ID
ReportGenerator.artTableColHdr.text=\u30C6\u30AD\u30B9\u30C8
ReportGenerator.artTableColHdr.domain=\u30C9\u30E1\u30A4\u30F3
ReportGenerator.artTableColHdr.devManufacturer=\u6A5F\u5668\u30E1\u30FC\u30AB\u30FC
ReportGenerator.artTableColHdr.devModel=\u6A5F\u5668\u30E2\u30C7\u30EB
ReportGenerator.artTableColHdr.personName=\u4EBA\u540D
ReportGenerator.artTableColHdr.phoneNumber=\u96FB\u8A71\u756A\u53F7
ReportGenerator.artTableColHdr.phoneNumHome=\u96FB\u8A71\u756A\u53F7\uFF08\u81EA\u5B85\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.title=\u30bf\u30a4\u30c8\u30eb
ReportGenerator.artTableColHdr.dateCreated=\u4f5c\u6210\u65e5\u4ed8
ReportGenerator.artTableColHdr.program=\u30d7\u30ed\u30b0\u30e9\u30e0
ReportGenerator.artTableColHdr.srcFile=\u30bd\u30fc\u30b9\u30d5\u30a1\u30a4\u30eb
ReportGenerator.artTableColHdr.dateTime=\u65e5\u4ed8\uff0f\u6642\u523b
ReportGenerator.artTableColHdr.name=\u540d\u524d
ReportGenerator.artTableColHdr.value=\u30d0\u30ea\u30e5\u30fc
ReportGenerator.artTableColHdr.dateAccessed=\u30a2\u30af\u30bb\u30b9\u65e5\u4ed8
ReportGenerator.artTableColHdr.referrer=\u30ea\u30d5\u30a1\u30e9
ReportGenerator.artTableColHdr.dest=\u30c7\u30b9\u30c6\u30a3\u30cd\u30fc\u30b7\u30e7\u30f3
ReportGenerator.artTableColHdr.sourceUrl=\u30bd\u30fc\u30b9URL
ReportGenerator.artTableColHdr.path=\u30d1\u30b9
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.preview=\u30d7\u30ec\u30d3\u30e5\u30fc
ReportGenerator.artTableColHdr.file=\u30d5\u30a1\u30a4\u30eb
ReportGenerator.artTableColHdr.size=\u30b5\u30a4\u30ba
ReportGenerator.artTableColHdr.deviceId=\u6a5f\u5668ID
ReportGenerator.artTableColHdr.text=\u30c6\u30ad\u30b9\u30c8
ReportGenerator.artTableColHdr.domain=\u30c9\u30e1\u30a4\u30f3
ReportGenerator.artTableColHdr.devManufacturer=\u6a5f\u5668\u30e1\u30fc\u30ab\u30fc
ReportGenerator.artTableColHdr.devModel=\u6a5f\u5668\u30e2\u30c7\u30eb
ReportGenerator.artTableColHdr.personName=\u4eba\u540d
ReportGenerator.artTableColHdr.phoneNumber=\u96fb\u8a71\u756a\u53f7
ReportGenerator.artTableColHdr.phoneNumHome=\u96fb\u8a71\u756a\u53f7\uff08\u81ea\u5b85\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.email=Email
ReportGenerator.artTableColHdr.msgType=\u30E1\u30C3\u30BB\u30FC\u30B8\u30BF\u30A4\u30D7
ReportGenerator.artTableColHdr.latitude=\u7DEF\u5EA6
ReportGenerator.artTableColHdr.longitude=\u7D4C\u5EA6
ReportGenerator.artTableColHdr.dateTaken=\u64AE\u5F71\u65E5\u4ED8
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.description=\u8AAC\u660E
ReportGenerator.artTableColHdr.startDateTime=\u958B\u59CB\u65E5\u4ED8\uFF0F\u6642\u523B
ReportGenerator.artTableColHdr.shortCut=\u30B7\u30E7\u30FC\u30C8\u30AB\u30C3\u30C8
ReportGenerator.artTableColHdr.endDateTime=\u4FEE\u4E86\u65E5\u4ED8\uFF0F\u6642\u523B
ReportGenerator.artTableColHdr.location=\u30ED\u30B1\u30FC\u30B7\u30E7\u30F3
ReportGenerator.artTableColHdr.deviceName=\u6A5F\u5668\u540D
ReportGenerator.artTableColHdr.deviceAddress=\u6A5F\u5668\u30A2\u30C9\u30EC\u30B9
ReportGenerator.artTableColHdr.altitude=\u6A19\u9AD8
ReportGenerator.artTableColHdr.locationAddress=\u30ED\u30B1\u30FC\u30B7\u30E7\u30F3\u30A2\u30C9\u30EC\u30B9
ReportGenerator.artTableColHdr.category=\u30AB\u30C6\u30B4\u30EA\u30FC
ReportGenerator.artTableColHdr.userId=\u30E6\u30FC\u30B6ID
ReportGenerator.artTableColHdr.password=\u30D1\u30B9\u30EF\u30FC\u30C9
ReportGenerator.artTableColHdr.replytoAddress=\u8FD4\u4FE1\u30A2\u30C9\u30EC\u30B9
ReportGenerator.artTableColHdr.mailServer=\u30E1\u30FC\u30EB\u30B5\u30FC\u30D0
ReportGenerator.artTableColHdr.tags=\u30BF\u30B0
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.thumbLink.tags=\u30BF\u30B0\uFF1A
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.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.h1=\u30EC\u30DD\u30FC\u30C8\u30CA\u30D3\u30B2\u30FC\u30B7\u30E7\u30F3
ReportHTML.writeNav.summary=\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.caseNum=\u30B1\u30FC\u30B9\u756A\u53F7\uFF1A
ReportHTML.writeSum.examiner=\u8ABF\u67FB\u62C5\u5F53\u8005\uFF1A
ReportHTML.writeSum.numImages=\u30A4\u30E1\u30FC\u30B8\u6570\uFF1A
ReportHTML.writeSum.path=\u30D1\u30B9\uFF1A
ReportProgressPanel.start.cancelButton.text=\u30AD\u30E3\u30F3\u30BB\u30EB
ReportProgressPanel.complete.processLbl.text=\u5B8C\u4E86
ReportProgressPanel.complete.cancelButton.text=\u5B8C\u4E86
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.reportWiz.title=\u30EC\u30DD\u30FC\u30C8\u3092\u751F\u6210
ReportWizardAction.toolBarButton.text=\u30EC\u30DD\u30FC\u30C8\u3092\u751F\u6210
ReportWizardPanel1.nextButton.text=\u6B21 >
ReportWizardPanel2.nextButton.text=\u6B21 >
ReportGenerator.artTableColHdr.direction=\u65B9\u5411
ReportGenerator.artTableColHdr.fromEmail=\u9001\u4FE1\u5143E\u30E1\u30FC\u30EB
ReportGenerator.artTableColHdr.toEmail=\u9001\u4FE1\u5148E\u30E1\u30FC\u30EB
ReportGenerator.artTableColHdr.fromPhoneNum=\u767A\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.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.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.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.imageInfoHeading=<h2>\u30A4\u30E1\u30FC\u30B8\u60C5\u5831\uFF1A</h2>
ReportHTML.writeSum.timezone=\u30BF\u30A4\u30E0\u30BE\u30FC\u30F3\uFF1A
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.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
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
ReportWizardFileOptionsPanel.finishButton.text=\u7D42\u4E86
ReportWizardFileOptionsVisualPanel.getName.text=\u30D5\u30A1\u30A4\u30EB\u30EC\u30DD\u30FC\u30C8\u3092\u8A2D\u5B9A
ReportWizardPanel1.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.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.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
ReportGenerator.artTableColHdr.msgType=\u30e1\u30c3\u30bb\u30fc\u30b8\u30bf\u30a4\u30d7
ReportGenerator.artTableColHdr.latitude=\u7def\u5ea6
ReportGenerator.artTableColHdr.longitude=\u7d4c\u5ea6
ReportGenerator.artTableColHdr.dateTaken=\u64ae\u5f71\u65e5\u4ed8
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.description=\u8aac\u660e
ReportGenerator.artTableColHdr.startDateTime=\u958b\u59cb\u65e5\u4ed8\uff0f\u6642\u523b
ReportGenerator.artTableColHdr.shortCut=\u30b7\u30e7\u30fc\u30c8\u30ab\u30c3\u30c8
ReportGenerator.artTableColHdr.endDateTime=\u4fee\u4e86\u65e5\u4ed8\uff0f\u6642\u523b
ReportGenerator.artTableColHdr.location=\u30ed\u30b1\u30fc\u30b7\u30e7\u30f3
ReportGenerator.artTableColHdr.deviceName=\u6a5f\u5668\u540d
ReportGenerator.artTableColHdr.deviceAddress=\u6a5f\u5668\u30a2\u30c9\u30ec\u30b9
ReportGenerator.artTableColHdr.altitude=\u6a19\u9ad8
ReportGenerator.artTableColHdr.locationAddress=\u30ed\u30b1\u30fc\u30b7\u30e7\u30f3\u30a2\u30c9\u30ec\u30b9
ReportGenerator.artTableColHdr.category=\u30ab\u30c6\u30b4\u30ea\u30fc
ReportGenerator.artTableColHdr.userId=\u30e6\u30fc\u30b6ID
ReportGenerator.artTableColHdr.password=\u30d1\u30b9\u30ef\u30fc\u30c9
ReportGenerator.artTableColHdr.replytoAddress=\u8fd4\u4fe1\u30a2\u30c9\u30ec\u30b9
ReportGenerator.artTableColHdr.mailServer=\u30e1\u30fc\u30eb\u30b5\u30fc\u30d0
ReportGenerator.artTableColHdr.tags=\u30bf\u30b0
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.thumbLink.tags=\u30bf\u30b0\uff1a
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.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.h1=\u30ec\u30dd\u30fc\u30c8\u30ca\u30d3\u30b2\u30fc\u30b7\u30e7\u30f3
ReportHTML.writeNav.summary=\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.caseNum=\u30b1\u30fc\u30b9\u756a\u53f7\uff1a
ReportHTML.writeSum.examiner=\u8abf\u67fb\u62c5\u5f53\u8005\uff1a
ReportHTML.writeSum.numImages=\u30a4\u30e1\u30fc\u30b8\u6570\uff1a
ReportHTML.writeSum.path=\u30d1\u30b9\uff1a
ReportProgressPanel.start.cancelButton.text=\u30ad\u30e3\u30f3\u30bb\u30eb
ReportProgressPanel.complete.processLbl.text=\u5b8c\u4e86
ReportProgressPanel.complete.cancelButton.text=\u5b8c\u4e86
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.reportWiz.title=\u30ec\u30dd\u30fc\u30c8\u3092\u751f\u6210
ReportWizardAction.toolBarButton.text=\u30ec\u30dd\u30fc\u30c8\u3092\u751f\u6210
ReportWizardPanel1.nextButton.text=\u6b21 >
ReportWizardPanel2.nextButton.text=\u6b21 >
ReportGenerator.artTableColHdr.direction=\u65b9\u5411
ReportGenerator.artTableColHdr.fromEmail=\u9001\u4fe1\u5143E\u30e1\u30fc\u30eb
ReportGenerator.artTableColHdr.toEmail=\u9001\u4fe1\u5148E\u30e1\u30fc\u30eb
ReportGenerator.artTableColHdr.fromPhoneNum=\u767a\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.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.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.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.imageInfoHeading=<h2>\u30a4\u30e1\u30fc\u30b8\u60c5\u5831\uff1a</h2>
ReportHTML.writeSum.timezone=\u30bf\u30a4\u30e0\u30be\u30fc\u30f3\uff1a
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.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
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
ReportWizardFileOptionsPanel.finishButton.text=\u7d42\u4e86
ReportWizardFileOptionsVisualPanel.getName.text=\u30d5\u30a1\u30a4\u30eb\u30ec\u30dd\u30fc\u30c8\u3092\u8a2d\u5b9a
ReportWizardPanel1.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.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.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.getName.text=Google Earth/KML
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
ReportBodyFile.generateReport.srcModuleName.text=TSK\u30DC\u30C7\u30A3\u30D5\u30A1\u30A4\u30EB
ReportExcel.endReport.srcModuleName.text=Excel\u30EC\u30DD\u30FC\u30C8
ReportGenerator.artTableColHdr.extension.text=\u62E1\u5F35\u5B50
ReportGenerator.artTableColHdr.mimeType.text=MIME\u30BF\u30A4\u30D7
ReportHTML.writeIndex.srcModuleName.text=HTML\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.count=\u30AB\u30A6\u30F3\u30C8
ReportGenerator.artTableColHdr.devMake=\u6A5F\u5668\u578B\u540D
ReportGenerator.artTableColHdr.latitudeEnd=\u5230\u7740\u7DEF\u5EA6
ReportGenerator.artTableColHdr.latitudeStart=\u51FA\u767A\u7DEF\u5EA6
ReportGenerator.artTableColHdr.localPath=\u30ED\u30FC\u30AB\u30EB\u30D1\u30B9
ReportGenerator.artTableColHdr.longitudeEnd=\u5230\u7740\u7D4C\u5EA6
ReportGenerator.artTableColHdr.longitudeStart=\u51FA\u767A\u7D4C\u5EA6
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.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.remotePath=\u30EA\u30E2\u30FC\u30C8\u30D1\u30B9
ReportGenerator.artTableColHdr.tskDateTimeRcvd=\u53D7\u4FE1\u65E5
ReportGenerator.artTableColHdr.tskDateTimeSent=\u9001\u4FE1\u65E5
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
ReportBodyFile.generateReport.srcModuleName.text=TSK\u30dc\u30c7\u30a3\u30d5\u30a1\u30a4\u30eb
ReportExcel.endReport.srcModuleName.text=Excel\u30ec\u30dd\u30fc\u30c8
ReportGenerator.artTableColHdr.extension.text=\u62e1\u5f35\u5b50
ReportGenerator.artTableColHdr.mimeType.text=MIME\u30bf\u30a4\u30d7
ReportHTML.writeIndex.srcModuleName.text=HTML\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.count=\u30ab\u30a6\u30f3\u30c8
ReportGenerator.artTableColHdr.devMake=\u6a5f\u5668\u578b\u540d
ReportGenerator.artTableColHdr.latitudeEnd=\u5230\u7740\u7def\u5ea6
ReportGenerator.artTableColHdr.latitudeStart=\u51fa\u767a\u7def\u5ea6
ReportGenerator.artTableColHdr.localPath=\u30ed\u30fc\u30ab\u30eb\u30d1\u30b9
ReportGenerator.artTableColHdr.longitudeEnd=\u5230\u7740\u7d4c\u5ea6
ReportGenerator.artTableColHdr.longitudeStart=\u51fa\u767a\u7d4c\u5ea6
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.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.remotePath=\u30ea\u30e2\u30fc\u30c8\u30d1\u30b9
ReportGenerator.artTableColHdr.tskDateTimeRcvd=\u53d7\u4fe1\u65e5
ReportGenerator.artTableColHdr.tskDateTimeSent=\u9001\u4fe1\u65e5
ReportGenerator.artTableColHdr.tskEmailBcc=E-Mail BCC
ReportGenerator.artTableColHdr.tskEmailCc=E-Mail CC
ReportGenerator.artTableColHdr.tskEmailFrom=E-Mail\u9001\u4FE1\u5143
ReportGenerator.artTableColHdr.tskEmailTo=E-Mail\u9001\u4FE1\u5148
ReportGenerator.artTableColHdr.tskGpsRouteCategory=\u30AB\u30C6\u30B4\u30EA
ReportGenerator.artTableColHdr.tskInterestingFilesCategory=\u30EB\u30FC\u30EB
ReportGenerator.artTableColHdr.tskMsgId=\u30E1\u30C3\u30BB\u30FC\u30B8ID
ReportGenerator.artTableColHdr.tskPath=\u30D1\u30B9
ReportGenerator.artTableColHdr.tskSetName=\u30BB\u30C3\u30C8\u540D
ReportGenerator.artTableColHdr.tskSubject=\u30B5\u30D6\u30B8\u30A7\u30AF\u30C8
ReportGenerator.artTableColHdr.urlDomainDecoded=URL\u30C9\u30E1\u30A4\u30F3
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.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.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.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.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.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.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.file=\u30D5\u30A1\u30A4\u30EB
ReportGenerator.htmlOutput.header.hash=\u30CF\u30C3\u30B7\u30E5
ReportGenerator.htmlOutput.header.size=\u30B5\u30A4\u30BA\uFF08\u30D0\u30A4\u30C8\uFF09
ReportGenerator.htmlOutput.header.tag=\u30BF\u30B0
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.timeModified=\u4FEE\u6B63\u65E5\u6642
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
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
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
ReportGenerationPanel.cancelButton.actionCommand=\u30AD\u30E3\u30F3\u30BB\u30EB
ReportGenerationPanel.cancelButton.text=\u30AD\u30E3\u30F3\u30BB\u30EB
ReportGenerator.artTableColHdr.tskEmailFrom=E-Mail\u9001\u4fe1\u5143
ReportGenerator.artTableColHdr.tskEmailTo=E-Mail\u9001\u4fe1\u5148
ReportGenerator.artTableColHdr.tskGpsRouteCategory=\u30ab\u30c6\u30b4\u30ea
ReportGenerator.artTableColHdr.tskInterestingFilesCategory=\u30eb\u30fc\u30eb
ReportGenerator.artTableColHdr.tskMsgId=\u30e1\u30c3\u30bb\u30fc\u30b8ID
ReportGenerator.artTableColHdr.tskPath=\u30d1\u30b9
ReportGenerator.artTableColHdr.tskSetName=\u30bb\u30c3\u30c8\u540d
ReportGenerator.artTableColHdr.tskSubject=\u30b5\u30d6\u30b8\u30a7\u30af\u30c8
ReportGenerator.artTableColHdr.urlDomainDecoded=URL\u30c9\u30e1\u30a4\u30f3
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.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.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.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.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.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.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.file=\u30d5\u30a1\u30a4\u30eb
ReportGenerator.htmlOutput.header.hash=\u30cf\u30c3\u30b7\u30e5
ReportGenerator.htmlOutput.header.size=\u30b5\u30a4\u30ba\uff08\u30d0\u30a4\u30c8\uff09
ReportGenerator.htmlOutput.header.tag=\u30bf\u30b0
ReportGenerator.htmlOutput.header.timeAccessed=\u30a2\u30af\u30bb\u30b9\u65e5\u6642
ReportGenerator.htmlOutput.header.timeCreated=\u4f5c\u6210\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.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
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
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.text=\u30ad\u30e3\u30f3\u30bb\u30eb

View File

@ -26,22 +26,16 @@
<Layout>
<DimensionLayout dim="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">
<Component id="titleLabel" min="-2" max="-2" attributes="0"/>
<EmptySpace min="0" pref="522" max="32767" attributes="0"/>
</Group>
<Group type="102" alignment="0" attributes="0">
<EmptySpace min="-2" max="-2" attributes="0"/>
<Group type="103" groupAlignment="0" attributes="0">
<Group type="102" alignment="1" attributes="0">
<EmptySpace min="0" pref="546" max="32767" attributes="0"/>
<Component id="cancelButton" min="-2" max="-2" attributes="0"/>
<EmptySpace type="unrelated" max="-2" attributes="0"/>
<Component id="closeButton" min="-2" max="-2" attributes="0"/>
</Group>
<Component id="reportPanel" alignment="0" pref="680" max="32767" attributes="0"/>
</Group>
<EmptySpace max="-2" attributes="0"/>
</Group>
@ -51,19 +45,13 @@
<Group type="103" groupAlignment="0" attributes="0">
<Group type="102" alignment="0" attributes="0">
<EmptySpace max="-2" attributes="0"/>
<Component id="titleLabel" min="-2" max="-2" 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"/>
<Component id="reportPanel" pref="344" max="32767" attributes="0"/>
<EmptySpace type="unrelated" max="-2" attributes="0"/>
<Group type="103" groupAlignment="3" attributes="0">
<Component id="closeButton" alignment="3" min="-2" max="-2" attributes="0"/>
<Component id="cancelButton" alignment="3" min="-2" max="-2" attributes="0"/>
</Group>
<EmptySpace max="-2" attributes="0"/>
<EmptySpace min="-2" max="-2" attributes="0"/>
</Group>
</Group>
</DimensionLayout>
@ -102,77 +90,30 @@
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="cancelButtonActionPerformed"/>
</Events>
</Component>
<Container class="javax.swing.JScrollPane" name="reportScrollPane">
<Container class="javax.swing.JPanel" name="reportPanel">
<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"/>
<Font bold="false" component="reportPanel" property="font" relativeSize="false" size="11"/>
</FontInfo>
</Property>
<Property name="preferredSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[600, 400]"/>
</Property>
</Properties>
<Layout class="org.netbeans.modules.form.compat2.layouts.support.JScrollPaneSupportLayout"/>
<SubComponents>
<Container class="javax.swing.JPanel" name="reportPanel">
<Properties>
<Property name="font" type="java.awt.Font" editor="org.netbeans.modules.form.editors2.FontEditor">
<FontInfo relative="true">
<Font bold="false" component="reportPanel" property="font" relativeSize="false" size="11"/>
</FontInfo>
</Property>
<Property name="preferredSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[600, 400]"/>
</Property>
</Properties>
<Layout>
<DimensionLayout dim="0">
<Group type="103" groupAlignment="0" attributes="0">
<EmptySpace min="0" pref="661" max="32767" attributes="0"/>
</Group>
</DimensionLayout>
<DimensionLayout dim="1">
<Group type="103" groupAlignment="0" attributes="0">
<EmptySpace min="0" pref="400" max="32767" attributes="0"/>
</Group>
</DimensionLayout>
</Layout>
</Container>
</SubComponents>
<Layout>
<DimensionLayout dim="0">
<Group type="103" groupAlignment="0" attributes="0">
<EmptySpace min="0" pref="0" max="32767" attributes="0"/>
</Group>
</DimensionLayout>
<DimensionLayout dim="1">
<Group type="103" groupAlignment="0" attributes="0">
<EmptySpace min="0" pref="344" max="32767" attributes="0"/>
</Group>
</DimensionLayout>
</Layout>
</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>

View File

@ -1,7 +1,7 @@
/*
* Autopsy Forensic Browser
*
* Copyright 2012 Basis Technology Corp.
* Copyright 2011-2016 Basis Technology Corp.
* Contact: carrier <at> sleuthkit <dot> org
*
* Licensed under the Apache License, Version 2.0 (the "License");
@ -20,69 +20,89 @@ package org.sleuthkit.autopsy.report;
import java.awt.*;
import java.awt.event.ActionListener;
import java.beans.PropertyChangeEvent;
import javax.swing.Box;
import javax.swing.JOptionPane;
import javax.swing.SwingUtilities;
import org.openide.util.NbBundle;
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 {
private GridBagConstraints c;
ReportProgressPanel progressPanel;
private Component glue;
private static final long serialVersionUID = 1L;
private final GridBagConstraints constraints;
private final Component glue;
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();
customInit();
}
private void customInit() {
reportPanel.setLayout(new GridBagLayout());
c = new GridBagConstraints();
c.fill = GridBagConstraints.BOTH;
c.gridx = 0;
c.gridy = 0;
c.weightx = 1.0;
constraints = new GridBagConstraints();
constraints.fill = GridBagConstraints.BOTH;
constraints.gridx = 0;
constraints.gridy = 0;
constraints.weightx = 1.0;
glue = Box.createVerticalGlue();
}
/**
* Add a ReportProgressPanel to this panel with the given report name and
* path.
* Adds a panel used by a report generation module to show progress to this
* panel.
*
* @param reportName report name
* @param reportPath report path
* @param reportName The report name.
* @param reportPath The report file path
*
* @return ReportProgressPanel progress panel to update
* @return The report generation progress panel.
*/
public ReportProgressPanel addReport(String reportName, String reportPath) {
// Remove the glue
ReportProgressPanel addReport(String reportName, String reportPath) {
/*
* Remove the "glue."
*/
reportPanel.remove(glue);
progressPanel = new ReportProgressPanel(reportName, reportPath);
c.weighty = 0.0;
c.anchor = GridBagConstraints.NORTH;
reportPanel.add(progressPanel, c);
c.gridy++;
constraints.weighty = 0.0;
constraints.anchor = GridBagConstraints.NORTH;
reportPanel.add(progressPanel, constraints);
constraints.gridy++;
// Add the glue back to the bottom
c.weighty = 1.0;
c.anchor = GridBagConstraints.PAGE_END;
reportPanel.add(glue, c);
/*
* Add the "glue" back to the bottom of the panel.
*/
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.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;
}
/**
* 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() {
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.
* 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();
cancelButton = new javax.swing.JButton();
reportScrollPane = new javax.swing.JScrollPane();
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));
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.setPreferredSize(new java.awt.Dimension(600, 400));
@ -153,53 +174,33 @@ class ReportGenerationPanel extends javax.swing.JPanel {
reportPanel.setLayout(reportPanelLayout);
reportPanelLayout.setHorizontalGroup(
reportPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGap(0, 661, Short.MAX_VALUE)
.addGap(0, 0, Short.MAX_VALUE)
);
reportPanelLayout.setVerticalGroup(
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);
this.setLayout(layout);
layout.setHorizontalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(optionSeparator)
.addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
.addGroup(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.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
.addGap(0, 546, Short.MAX_VALUE)
.addComponent(cancelButton)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
.addComponent(closeButton)))
.addComponent(closeButton))
.addComponent(reportPanel, javax.swing.GroupLayout.DEFAULT_SIZE, 680, Short.MAX_VALUE))
.addContainerGap())
);
layout.setVerticalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup()
.addContainerGap()
.addComponent(titleLabel)
.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)
.addComponent(reportPanel, javax.swing.GroupLayout.DEFAULT_SIZE, 344, Short.MAX_VALUE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
.addComponent(closeButton)
@ -225,17 +226,10 @@ class ReportGenerationPanel extends javax.swing.JPanel {
}
}//GEN-LAST:event_cancelButtonActionPerformed
void addCloseAction(ActionListener l) {
this.actionListener = l;
}
// Variables declaration - do not modify//GEN-BEGIN:variables
private javax.swing.JButton cancelButton;
private javax.swing.JButton closeButton;
private javax.swing.JSeparator optionSeparator;
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
}

View File

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

View File

@ -560,15 +560,6 @@ class ReportHTML implements TableReportModule {
return;
}
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().
StringBuilder localFileLink = new StringBuilder();
// 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">
<EmptySpace max="-2" attributes="0"/>
<Group type="103" groupAlignment="0" attributes="0">
<Component id="processingLabel" max="32767" attributes="0"/>
<Group type="102" alignment="0" attributes="0">
<Component id="reportProgressBar" max="32767" attributes="0"/>
<EmptySpace min="-2" pref="58" max="-2" attributes="0"/>
</Group>
<Component id="statusMessageLabel" max="32767" attributes="0"/>
<Component id="reportProgressBar" alignment="0" max="32767" attributes="0"/>
<Group type="102" alignment="0" attributes="0">
<Component id="reportLabel" min="-2" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
@ -49,17 +46,17 @@
<DimensionLayout dim="1">
<Group type="103" groupAlignment="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"/>
<EmptySpace max="-2" attributes="0"/>
<EmptySpace min="-2" max="-2" attributes="0"/>
<Group type="103" groupAlignment="3" 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"/>
</Group>
<EmptySpace min="0" pref="0" max="-2" attributes="0"/>
<Component id="processingLabel" min="-2" max="-2" attributes="0"/>
<EmptySpace pref="20" max="32767" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Component id="statusMessageLabel" min="-2" max="-2" attributes="0"/>
<EmptySpace min="-2" pref="13" max="-2" attributes="0"/>
</Group>
</Group>
</DimensionLayout>
@ -96,18 +93,7 @@
<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;)"/>
</Property>
</Properties>
</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>
<Property name="verticalAlignment" type="int" value="1"/>
</Properties>
</Component>
<Component class="javax.swing.JLabel" name="separationLabel">
@ -122,5 +108,12 @@
</Property>
</Properties>
</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>
</Form>

View File

@ -1,7 +1,7 @@
/*
* Autopsy Forensic Browser
*
* Copyright 2012 Basis Technology Corp.
* Copyright 2011-2016 Basis Technology Corp.
* Contact: carrier <at> sleuthkit <dot> org
*
* Licensed under the Apache License, Version 2.0 (the "License");
@ -19,22 +19,32 @@
package org.sleuthkit.autopsy.report;
import org.openide.util.NbBundle;
import java.awt.*;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.beans.PropertyChangeListener;
import java.beans.PropertyChangeSupport;
import java.io.File;
import java.io.IOException;
import java.util.logging.Level;
import org.sleuthkit.autopsy.coreutils.Logger;
/**
* A panel used by a report generation module to show progress.
*/
public class ReportProgressPanel extends javax.swing.JPanel {
private static final long serialVersionUID = 1L;
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 {
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) {
initComponents();
customInit(reportName, reportPath);
}
private void customInit(String reportName, String reportPath) {
reportProgressBar.setIndeterminate(true);
reportProgressBar.setMaximum(100);
reportLabel.setText(reportName);
processingLabel.setText(NbBundle.getMessage(this.getClass(), "ReportProgressPanel.progress.queuing"));
STATUS = ReportStatus.QUEUING;
if (reportPath != null) {
statusMessageLabel.setText(NbBundle.getMessage(this.getClass(), "ReportProgressPanel.progress.queuing"));
status = ReportStatus.QUEUING;
if (null != reportPath) {
pathLabel.setText("<html><u>" + shortenPath(reportPath) + "</u></html>"); //NON-NLS
pathLabel.setToolTipText(reportPath);
// Add the "link" effect to the pathLabel
final String linkPath = reportPath;
String linkPath = reportPath;
pathLabel.addMouseListener(new MouseListener() {
@Override
public void mouseClicked(MouseEvent e) {
public void mouseClicked(MouseEvent mouseEvent) {
}
@Override
public void mousePressed(MouseEvent e) {
public void mousePressed(MouseEvent mouseEvent) {
}
@Override
public void mouseReleased(MouseEvent e) {
public void mouseReleased(MouseEvent mouseEvent) {
File file = new File(linkPath);
try {
Desktop.getDesktop().open(file);
} catch (IOException ex) {
} catch (IllegalArgumentException ex) {
} catch (IOException ioex) {
logger.log(Level.SEVERE, "Error opening report file", ioex);
} catch (IllegalArgumentException iaEx) {
logger.log(Level.SEVERE, "Error opening report file", iaEx);
try {
// try to open the parent path if the file doens't exist
Desktop.getDesktop().open(file.getParentFile());
} catch (IOException ex1) {
} catch (IOException ioEx2) {
logger.log(Level.SEVERE, "Error opening report file parent", ioEx2);
}
}
}
@Override
public void mouseEntered(MouseEvent e) {
public void mouseEntered(MouseEvent e3) {
pathLabel.setForeground(Color.DARK_GRAY);
setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR));
}
@Override
public void mouseExited(MouseEvent e) {
public void mouseExited(MouseEvent e4) {
pathLabel.setForeground(Color.BLACK);
setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
}
});
} else {
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) {
if (path.length() > 100) {
path = path.substring(0, 10 + path.substring(10).indexOf(File.separator) + 1) + "..."
+ path.substring((path.length() - 70) + path.substring(path.length() - 70).indexOf(File.separator));
}
return path;
@Override
public void addPropertyChangeListener(PropertyChangeListener listener) {
this.pcs.addPropertyChangeListener(listener);
}
/**
* 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() {
return STATUS;
return status;
}
/**
* Start the JProgressBar for this report.
*
* Enables the cancelButton, updates the processingLabel, and changes this
* report's ReportStatus.
* Starts the progress bar component of this panel.
*/
public void start() {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
processingLabel.setText(NbBundle.getMessage(this.getClass(), "ReportProgressPanel.start.progress.text"));
STATUS = ReportStatus.RUNNING;
}
EventQueue.invokeLater(() -> {
statusMessageLabel.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) {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
if (STATUS != ReportStatus.CANCELED) {
reportProgressBar.setMaximum(max);
}
public void setMaximumProgress(int max) {
EventQueue.invokeLater(() -> {
if (status != ReportStatus.CANCELED) {
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() {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
if (STATUS != ReportStatus.CANCELED) {
reportProgressBar.setValue(reportProgressBar.getValue() + 1);
}
EventQueue.invokeLater(() -> {
if (status != ReportStatus.CANCELED) {
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) {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
if (STATUS != ReportStatus.CANCELED) {
reportProgressBar.setValue(value);
}
public void setProgress(int value) {
EventQueue.invokeLater(() -> {
if (status != ReportStatus.CANCELED) {
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.
*
* @param indeterminate sets the JProgressBar to be indeterminate if true,
* determinate otherwise
* @param indeterminate True if the progress bar should be set to
* indeterminate.
*/
public void setIndeterminate(final boolean indeterminate) {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
if (STATUS != ReportStatus.CANCELED) {
reportProgressBar.setIndeterminate(indeterminate);
}
public void setIndeterminate(boolean indeterminate) {
EventQueue.invokeLater(() -> {
if (status != ReportStatus.CANCELED) {
reportProgressBar.setIndeterminate(indeterminate);
}
});
}
/**
* Change the text of this report's status label. The text given will be the
* full text used. e.g. updateStatusLabel("Now processing files...") sets
* the label to "Now processing files..."
* 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 status String to use as status
* @param statusMessage String to use as label text.
*/
public void updateStatusLabel(final String status) {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
if (STATUS != ReportStatus.CANCELED) {
processingLabel.setText(status);
}
public void updateStatusLabel(String statusMessage) {
EventQueue.invokeLater(() -> {
if (status != ReportStatus.CANCELED) {
statusMessageLabel.setText(statusMessage);
}
});
}
/**
* Declare the report completed. This will fill the JProgressBar, update the
* cancelButton to completed, and disallow any cancellation of this report.
* Makes the components of this panel indicate the final status of
* generation of the 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.
* @param reportStatus The final status, must be COMPLETE or ERROR.
*/
public void complete(ReportStatus reportStatus) {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
// make sure we disable an indeterminate
reportProgressBar.setIndeterminate(false);
if (STATUS != ReportStatus.CANCELED) {
switch (reportStatus) {
case COMPLETE: {
STATUS = ReportStatus.COMPLETE;
processingLabel.setForeground(Color.BLACK);
processingLabel.setText(
NbBundle.getMessage(this.getClass(), "ReportProgressPanel.complete.processLbl.text"));
reportProgressBar.setValue(reportProgressBar.getMaximum());
reportProgressBar.setStringPainted(true);
// set reportProgressBar color as green.
reportProgressBar.setForeground(new Color(50, 205, 50));
reportProgressBar.setString("Complete"); //NON-NLS
break;
}
case ERROR: {
STATUS = ReportStatus.ERROR;
processingLabel.setForeground(new Color(178, 34, 34));
processingLabel.setText(
NbBundle.getMessage(this.getClass(), "ReportProgressPanel.complete.processLb2.text"));
reportProgressBar.setValue(reportProgressBar.getMaximum());
reportProgressBar.setStringPainted(true);
// set reportProgressBar color as red.
reportProgressBar.setForeground(new Color(178, 34, 34));
reportProgressBar.setString("Error"); //NON-NLS
break;
}
// add finer grained result codes here.
default: {
logger.log(Level.SEVERE, "Invalid ReportStatus code {0}", reportStatus); //NON-NLS
break;
}
EventQueue.invokeLater(() -> {
reportProgressBar.setIndeterminate(false);
if (status != ReportStatus.CANCELED) {
switch (reportStatus) {
case COMPLETE: {
ReportStatus oldValue = status;
status = ReportStatus.COMPLETE;
statusMessageLabel.setForeground(Color.BLACK);
statusMessageLabel.setText(NbBundle.getMessage(this.getClass(), "ReportProgressPanel.complete.processLbl.text"));
reportProgressBar.setValue(reportProgressBar.getMaximum());
reportProgressBar.setStringPainted(true);
reportProgressBar.setForeground(GREEN);
reportProgressBar.setString("Complete"); //NON-NLS
pcs.firePropertyChange(ReportStatus.COMPLETE.toString(), oldValue, status);
break;
}
case ERROR: {
ReportStatus oldValue = status;
status = ReportStatus.ERROR;
statusMessageLabel.setForeground(RED);
statusMessageLabel.setText(NbBundle.getMessage(this.getClass(), "ReportProgressPanel.complete.processLb2.text"));
reportProgressBar.setValue(reportProgressBar.getMaximum());
reportProgressBar.setStringPainted(true);
reportProgressBar.setForeground(RED);
reportProgressBar.setString("Error"); //NON-NLS
pcs.firePropertyChange(ReportStatus.COMPLETE.toString(), oldValue, status);
break;
}
default: {
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();
reportLabel = new javax.swing.JLabel();
pathLabel = new javax.swing.JLabel();
processingLabel = new javax.swing.JLabel();
separationLabel = new javax.swing.JLabel();
statusMessageLabel = new javax.swing.JLabel();
setFont(getFont().deriveFont(getFont().getStyle() & ~java.awt.Font.BOLD, 11));
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));
org.openide.awt.Mnemonics.setLocalizedText(pathLabel, org.openide.util.NbBundle.getMessage(ReportProgressPanel.class, "ReportProgressPanel.pathLabel.text")); // NOI18N
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
pathLabel.setVerticalAlignment(javax.swing.SwingConstants.TOP);
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(statusMessageLabel, org.openide.util.NbBundle.getMessage(ReportProgressPanel.class, "ReportProgressPanel.statusMessageLabel.text")); // NOI18N
javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
this.setLayout(layout);
layout.setHorizontalGroup(
@ -330,10 +347,8 @@ public class ReportProgressPanel extends javax.swing.JPanel {
.addGroup(layout.createSequentialGroup()
.addContainerGap()
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(processingLabel, 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)
.addGap(58, 58, 58))
.addComponent(statusMessageLabel, 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)
.addGroup(layout.createSequentialGroup()
.addComponent(reportLabel)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
@ -350,45 +365,32 @@ public class ReportProgressPanel extends javax.swing.JPanel {
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
.addComponent(reportLabel)
.addComponent(pathLabel)
.addComponent(pathLabel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addComponent(separationLabel))
.addGap(0, 0, 0)
.addComponent(processingLabel)
.addContainerGap(20, Short.MAX_VALUE))
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(statusMessageLabel)
.addGap(13, 13, 13))
);
}// </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
private javax.swing.JLabel pathLabel;
private javax.swing.JLabel processingLabel;
private javax.swing.JLabel reportLabel;
private javax.swing.JProgressBar reportProgressBar;
private javax.swing.JLabel separationLabel;
private javax.swing.JLabel statusMessageLabel;
// 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_TimeLineTopComponent=Timeline Window
HINT_TimeLineTopComponent=This is a Timeline window
@ -24,7 +24,5 @@ TimelinePanel.jButton7.text=3d
TimelinePanel.jButton2.text=1m
TimelinePanel.jButton3.text=3m
TimelinePanel.jButton4.text=2w
OpenTimelineAction.title=Timeline
OpenTimeLineAction.msgdlg.text=Could not create timeline, there are no data sources.
ProgressWindow.progressHeader.text=\

View File

@ -1,7 +1,7 @@
/*
* Autopsy Forensic Browser
*
* Copyright 2013 Basis Technology Corp.
* Copyright 2013-16 Basis Technology Corp.
* Contact: carrier <at> sleuthkit <dot> org
*
* Licensed under the Apache License, Version 2.0 (the "License");
@ -18,8 +18,8 @@
*/
package org.sleuthkit.autopsy.timeline;
import java.io.IOException;
import java.util.logging.Level;
import javax.swing.JOptionPane;
import org.openide.awt.ActionID;
import org.openide.awt.ActionReference;
import org.openide.awt.ActionReferences;
@ -27,10 +27,10 @@ import org.openide.awt.ActionRegistration;
import org.openide.util.HelpCtx;
import org.openide.util.NbBundle;
import org.openide.util.actions.CallableSystemAction;
import org.openide.windows.WindowManager;
import org.sleuthkit.autopsy.casemodule.Case;
import org.sleuthkit.autopsy.core.Installer;
import org.sleuthkit.autopsy.coreutils.Logger;
import org.sleuthkit.autopsy.coreutils.MessageNotifyUtil;
import org.sleuthkit.autopsy.coreutils.ThreadConfined;
@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();
}
@NbBundle.Messages({
"OpenTimelineAction.settingsErrorMessage=Failed to initialize timeline settings.",
"OpenTimeLineAction.msgdlg.text=Could not create timeline, there are no data sources."})
@Override
@ThreadConfined(type = ThreadConfined.ThreadType.AWT)
public void performAction() {
//check case
if (!Case.isCaseOpen()) {
return;
try {
Case currentCase = Case.getCurrentCase();
if (currentCase.hasData() == false) {
MessageNotifyUtil.Message.info(Bundle.OpenTimeLineAction_msgdlg_text());
LOGGER.log(Level.INFO, "Could not create timeline, there are no data sources.");// NON-NLS
return;
}
try {
if (timeLineController == null) {
timeLineController = new TimeLineController(currentCase);
} else if (timeLineController.getAutopsyCase() != currentCase) {
timeLineController.shutDownTimeLine();
timeLineController = new TimeLineController(currentCase);
}
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.
}
final Case currentCase = Case.getCurrentCase();
if (currentCase.hasData() == false) {
JOptionPane.showMessageDialog(WindowManager.getDefault().getMainWindow(),
NbBundle.getMessage(this.getClass(), "OpenTimeLineAction.msgdlg.text"));
LOGGER.log(Level.INFO, "Could not create timeline, there are no data sources.");// NON-NLS
return;
}
if (timeLineController == null) {
timeLineController = new TimeLineController(currentCase);
} else if (timeLineController.getAutopsyCase() != currentCase) {
timeLineController.closeTimeLine();
timeLineController = new TimeLineController(currentCase);
}
timeLineController.openTimeLine();
}
@Override
public String getName() {
return NbBundle.getMessage(TimeLineTopComponent.class, "OpenTimelineAction.title");
return NbBundle.getMessage(OpenTimelineAction.class, "CTL_MakeTimeline");
}
@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
*
* Copyright 2015 Basis Technology Corp.
* Copyright 2015-16 Basis Technology Corp.
* Contact: carrier <at> sleuthkit <dot> org
*
* Licensed under the Apache License, Version 2.0 (the "License");
@ -61,9 +61,9 @@ public class PromptDialogManager {
static {
Image x = null;
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) {
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;
}
@ -75,6 +75,12 @@ public class PromptDialogManager {
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)
boolean bringCurrentDialogToFront() {
if (currentDialog != null && currentDialog.isShowing()) {
@ -86,11 +92,12 @@ public class PromptDialogManager {
@NbBundle.Messages({"PromptDialogManager.progressDialog.title=Populating Timeline Data"})
@ThreadConfined(type = ThreadConfined.ThreadType.JFX)
public void showProgressDialog(CancellationProgressTask<?> task) {
void showProgressDialog(CancellationProgressTask<?> task) {
currentDialog = new ProgressDialog(task);
currentDialog.headerTextProperty().bind(task.titleProperty());
setDialogIcons(currentDialog);
currentDialog.initModality(Modality.NONE);
currentDialog.setTitle(Bundle.PromptDialogManager_progressDialog_title());
setDialogIcons(currentDialog);
currentDialog.headerTextProperty().bind(task.titleProperty());
DialogPane dialogPane = currentDialog.getDialogPane();
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.
task.setOnCancelled(cancelled -> currentDialog.close());
task.setOnSucceeded(succeeded -> currentDialog.close());
task.setOnFailed(failed -> currentDialog.close());
dialogPane.getButtonTypes().setAll(ButtonType.CANCEL);
final Node cancelButton = dialogPane.lookupButton(ButtonType.CANCEL);
cancelButton.disableProperty().bind(task.cancellableProperty().not());
@ -115,14 +124,7 @@ public class PromptDialogManager {
@ThreadConfined(type = ThreadConfined.ThreadType.JFX)
static private void setDialogIcons(Dialog<?> dialog) {
Stage stage = (Stage) dialog.getDialogPane().getScene().getWindow();
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());
((Stage) dialog.getDialogPane().getScene().getWindow()).getIcons().setAll(LOGO);
}
/**
@ -139,7 +141,7 @@ public class PromptDialogManager {
currentDialog.initModality(Modality.APPLICATION_MODAL);
currentDialog.setHeaderText(Bundle.PromptDialogManager_confirmDuringIngest_headerText());
setDialogIcons(currentDialog);
setDialogTitle(currentDialog);
currentDialog.setTitle(Bundle.Timeline_confirmation_dialogs_title());
return currentDialog.showAndWait().map(SHOW_TIMELINE::equals).orElse(false);
}
@ -152,7 +154,7 @@ public class PromptDialogManager {
currentDialog.initModality(Modality.APPLICATION_MODAL);
currentDialog.setHeaderText(Bundle.PromptDialogManager_rebuildPrompt_headerText());
setDialogIcons(currentDialog);
setDialogTitle(currentDialog);
currentDialog.setTitle(Bundle.Timeline_confirmation_dialogs_title());
DialogPane dialogPane = currentDialog.getDialogPane();
ListView<String> listView = new ListView<>(FXCollections.observableArrayList(rebuildReasons));

View File

@ -1,7 +1,7 @@
/*
* Autopsy Forensic Browser
*
* Copyright 2014-2015 Basis Technology Corp.
* Copyright 2014-2016 Basis Technology Corp.
* Contact: carrier <at> sleuthkit <dot> org
*
* 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.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.io.IOException;
import java.time.ZoneId;
import java.util.ArrayList;
import java.util.Collection;
@ -31,9 +30,10 @@ import java.util.TimeZone;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.logging.Level;
import javafx.application.Platform;
import javafx.beans.InvalidationListener;
import javafx.beans.Observable;
import javafx.beans.property.ReadOnlyBooleanProperty;
import javafx.beans.property.ReadOnlyBooleanWrapper;
@ -49,7 +49,6 @@ import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.concurrent.Task;
import javafx.concurrent.Worker;
import javafx.scene.control.Dialog;
import javax.annotation.concurrent.GuardedBy;
import javax.annotation.concurrent.Immutable;
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.EventTypeZoomLevel;
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}
@ -139,9 +135,6 @@ public class TimeLineController {
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
* user hint/information when it is not empty
@ -156,12 +149,13 @@ public class TimeLineController {
status.set(string);
}
private final Case autoCase;
private final PerCaseTimelineProperties perCaseTimelineProperties;
@ThreadConfined(type = ThreadConfined.ThreadType.JFX)
private final ObservableList<DescriptionFilter> quickHideMaskFilters = FXCollections.observableArrayList();
private final ObservableList<DescriptionFilter> quickHideFilters = FXCollections.observableArrayList();
public ObservableList<DescriptionFilter> getQuickHideFilters() {
return quickHideMaskFilters;
return quickHideFilters;
}
/**
@ -219,13 +213,12 @@ public class TimeLineController {
@GuardedBy("this")
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)
@GuardedBy("this")
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() {
return selectedEventIDs;
@ -241,14 +234,8 @@ public class TimeLineController {
return selectedTimeRange.getReadOnlyProperty();
}
public ReadOnlyBooleanProperty getNewEventsFlag() {
return newEventsFlag.getReadOnlyProperty();
}
private final ReadOnlyBooleanWrapper needsHistogramRebuild = new ReadOnlyBooleanWrapper(false);
public ReadOnlyBooleanProperty getNeedsHistogramRebuild() {
return needsHistogramRebuild.getReadOnlyProperty();
public ReadOnlyBooleanProperty eventsDBStaleProperty() {
return eventsDBStale.getReadOnlyProperty();
}
synchronized public ReadOnlyBooleanProperty getCanAdvance() {
@ -258,28 +245,26 @@ public class TimeLineController {
synchronized public ReadOnlyBooleanProperty 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);
public TimeLineController(Case autoCase) {
public TimeLineController(Case autoCase) throws IOException {
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
* filter to be in sync, and expose that as propery from
* TimeLineController. Do we need to do this with datasource or hash hit
* filters?
*/
historyManager.currentState().addListener(new InvalidationListener() {
public void invalidated(Observable observable) {
ZoomParams historyManagerParams = historyManager.getCurrentState();
eventsRepository.syncTagsFilter(historyManagerParams.getFilter().getTagsFilter());
currentParams.set(historyManagerParams);
}
historyManager.currentState().addListener((Observable observable) -> {
ZoomParams historyManagerParams = historyManager.getCurrentState();
eventsRepository.syncTagsFilter(historyManagerParams.getFilter().getTagsFilter());
currentParams.set(historyManagerParams);
});
eventsRepository = new EventsRepository(autoCase, currentParams.getReadOnlyProperty());
filteredEvents = eventsRepository.getEventsModel();
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
* aborted after prompt about ingest running. True if the repo was
* rebuilt.
* @param repoBuilder
*/
@ThreadConfined(type = ThreadConfined.ThreadType.JFX)
void rebuildRepo() {
private void rebuildRepoHelper(Function<Consumer<Worker.State>, CancellationProgressTask<?>> repoBuilder) {
SwingUtilities.invokeLater(this::closeTimelineWindow);
final CancellationProgressTask<?> rebuildRepository = eventsRepository.rebuildRepository();
rebuildRepository.stateProperty().addListener((stateProperty, oldState, newSate) -> {
boolean ingestRunning = IngestManager.getInstance().isIngestRunning();
final CancellationProgressTask<?> rebuildRepository = repoBuilder.apply(newSate -> {
setIngestRunning(ingestRunning);
//this will be on JFX thread
if (newSate == Worker.State.SUCCEEDED) {
//TODO: this looks hacky. what is going on? should this be an event?
needsHistogramRebuild.set(true);
needsHistogramRebuild.set(false);
SwingUtilities.invokeLater(TimeLineController.this::showWindow);
//TODO: should this be an event?
newEventsFlag.set(false);
historyManager.reset(filteredEvents.zoomParametersProperty().get());
TimeLineController.this.showFullRange();
switch (newSate) {
case SUCCEEDED:
setEventsDBStale(false);
SwingUtilities.invokeLater(TimeLineController.this::showWindow);
historyManager.reset(filteredEvents.zoomParametersProperty().get());
TimeLineController.this.showFullRange();
break;
case FAILED:
case CANCELLED:
setEventsDBStale(true);
break;
}
});
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
* tags table and rebuild it by querying for all the tags and inserting them
* in to the TimeLine DB.
*
*/
@ThreadConfined(type = ThreadConfined.ThreadType.JFX)
void rebuildTagsTable() {
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);
rebuildRepoHelper(eventsRepository::rebuildTags);
}
@ThreadConfined(type = ThreadConfined.ThreadType.AWT)
@ -370,7 +353,7 @@ public class TimeLineController {
}
@ThreadConfined(type = ThreadConfined.ThreadType.AWT)
public void closeTimeLine() {
public void shutDownTimeLine() {
if (mainFrame != null) {
listeningToAutopsy = false;
IngestManager.getInstance().removeIngestModuleEventListener(ingestModuleListener);
@ -409,7 +392,7 @@ public class TimeLineController {
/*
* if the repo was not rebuilt at minimum rebuild the tags which
* 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?
*/
if (checkAndPromptForRebuild() == false) {
@ -425,7 +408,7 @@ public class TimeLineController {
@ThreadConfined(type = ThreadConfined.ThreadType.JFX)
private boolean checkAndPromptForRebuild() {
//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();
return true;
}
@ -440,7 +423,6 @@ public class TimeLineController {
return false;
}
@SuppressWarnings("deprecation") // TODO (EUR-733): Do not use SleuthkitCase.getLastObjectId
@ThreadConfined(type = ThreadConfined.ThreadType.ANY)
@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.",
@ -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."})
private ArrayList<String> getRebuildReasons() {
ArrayList<String> rebuildReasons = new ArrayList<>();
//if ingest was running during last rebuild, prompt to rebuild
if (eventsRepository.getWasIngestRunning()) {
rebuildReasons.add(Bundle.TimeLineController_rebuildReasons_ingestWasRunning());
}
final SleuthkitCase sleuthkitCase = autoCase.getSleuthkitCase();
try {
//if the last artifact and object ids don't match between skc and tldb, prompt to rebuild
if (sleuthkitCase.getLastObjectId() != eventsRepository.getLastObjID()
|| getCaseLastArtifactID(sleuthkitCase) != eventsRepository.getLastArtfactID()) {
rebuildReasons.add(Bundle.TimeLineController_rebuildReasons_outOfDate());
//if ingest was running during last rebuild, prompt to rebuild
if (perCaseTimelineProperties.wasIngestRunning()) {
rebuildReasons.add(Bundle.TimeLineController_rebuildReasons_ingestWasRunning());
}
} 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
} catch (IOException ex) {
LOGGER.log(Level.SEVERE, "Error determing the state of the timeline db. We will assume the it is out of date.", ex); // NON-NLS
MessageNotifyUtil.Notify.error(Bundle.TimeLineController_errorTitle(),
Bundle.TimeLineController_outOfDate_errorMessage());
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 (eventsRepository.hasNewColumns() == false) {
rebuildReasons.add(Bundle.TimeLineController_rebuildReasons_incompleteOldSchema());
@ -474,21 +456,6 @@ public class TimeLineController {
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
* 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 {
@Override
@ -773,12 +772,10 @@ public class TimeLineController {
switch (IngestManager.IngestModuleEvent.valueOf(evt.getPropertyName())) {
case CONTENT_CHANGED:
case DATA_ADDED:
break;
case DATA_ADDED:
case FILE_DONE:
Platform.runLater(() -> {
newEventsFlag.set(true);
});
Platform.runLater(() -> setEventsDBStale(true));
break;
}
}
@ -804,32 +801,26 @@ public class TimeLineController {
public void propertyChange(PropertyChangeEvent evt) {
switch (Case.Events.valueOf(evt.getPropertyName())) {
case BLACKBOARD_ARTIFACT_TAG_ADDED:
executor.submit(() -> {
filteredEvents.handleArtifactTagAdded((BlackBoardArtifactTagAddedEvent) evt);
});
executor.submit(() -> filteredEvents.handleArtifactTagAdded((BlackBoardArtifactTagAddedEvent) evt));
break;
case BLACKBOARD_ARTIFACT_TAG_DELETED:
executor.submit(() -> {
filteredEvents.handleArtifactTagDeleted((BlackBoardArtifactTagDeletedEvent) evt);
});
executor.submit(() -> filteredEvents.handleArtifactTagDeleted((BlackBoardArtifactTagDeletedEvent) evt));
break;
case CONTENT_TAG_ADDED:
executor.submit(() -> {
filteredEvents.handleContentTagAdded((ContentTagAddedEvent) evt);
});
executor.submit(() -> filteredEvents.handleContentTagAdded((ContentTagAddedEvent) evt));
break;
case CONTENT_TAG_DELETED:
executor.submit(() -> {
filteredEvents.handleContentTagDeleted((ContentTagDeletedEvent) evt);
});
executor.submit(() -> filteredEvents.handleContentTagDeleted((ContentTagDeletedEvent) evt));
break;
case DATA_SOURCE_ADDED:
SwingUtilities.invokeLater(TimeLineController.this::confirmOutOfDateRebuildIfWindowOpen);
Platform.runLater(() -> {
setEventsDBStale(true);
SwingUtilities.invokeLater(TimeLineController.this::confirmOutOfDateRebuildIfWindowOpen);
});
break;
case CURRENT_CASE:
OpenTimelineAction.invalidateController();
SwingUtilities.invokeLater(TimeLineController.this::closeTimeLine);
SwingUtilities.invokeLater(TimeLineController.this::shutDownTimeLine);
break;
}
}

View File

@ -42,7 +42,7 @@ import org.sleuthkit.datamodel.TskCoreException;
public enum MiscTypes implements EventType, ArtifactEventType {
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 AttributeExtractor(new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_MESSAGE_TYPE)),
artf -> {
@ -56,7 +56,7 @@ public enum MiscTypes implements EventType, ArtifactEventType {
},
new AttributeExtractor(new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_TEXT))),
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 AttributeExtractor(new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_PROG_NAME)),
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
}),
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 AttributeExtractor(new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_PROG_NAME)),
artf -> {
@ -78,13 +78,13 @@ public enum MiscTypes implements EventType, ArtifactEventType {
},
EMPTY_EXTRACTOR),
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 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_DIRECTION))),
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),
artf -> {
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_EMAIL_CONTENT_PLAIN))),
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 AttributeExtractor(new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_PATH)).andThen(
(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
TypeUtils.fromEnum(ARTIFACT_TYPE.TSK_INSTALLED_PROG),
new BlackboardArtifact.Type(ARTIFACT_TYPE.TSK_INSTALLED_PROG),
new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_DATETIME),
new AttributeExtractor(new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_PROG_NAME)),
EMPTY_EXTRACTOR,
EMPTY_EXTRACTOR),
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 AttributeExtractor(new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_DEVICE_MAKE)),
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";
}),
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 AttributeExtractor(new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_DEVICE_MAKE)),
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"),
"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),
TopPrivateDomainExtractor.getInstance(),
new AttributeExtractor(new BlackboardAttribute.Type(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_PATH)),
@ -61,7 +61,7 @@ public enum WebTypes implements EventType, ArtifactEventType {
//TODO: review description separators
WEB_COOKIE(NbBundle.getMessage(WebTypes.class, "WebTypes.webCookies.name"),
"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),
TopPrivateDomainExtractor.getInstance(),
new AttributeExtractor(new BlackboardAttribute.Type(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_NAME)),
@ -69,7 +69,7 @@ public enum WebTypes implements EventType, ArtifactEventType {
//TODO: review description separators
WEB_BOOKMARK(NbBundle.getMessage(WebTypes.class, "WebTypes.webBookmarks.name"),
"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),
TopPrivateDomainExtractor.getInstance(),
new AttributeExtractor(new BlackboardAttribute.Type(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_URL)),
@ -77,7 +77,7 @@ public enum WebTypes implements EventType, ArtifactEventType {
//TODO: review description separators
WEB_HISTORY(NbBundle.getMessage(WebTypes.class, "WebTypes.webHistory.name"),
"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),
TopPrivateDomainExtractor.getInstance(),
new AttributeExtractor(new BlackboardAttribute.Type(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_URL)),
@ -85,7 +85,7 @@ public enum WebTypes implements EventType, ArtifactEventType {
//TODO: review description separators
WEB_SEARCH(NbBundle.getMessage(WebTypes.class, "WebTypes.webSearch.name"),
"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 AttributeExtractor(new BlackboardAttribute.Type(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_TEXT)),
TopPrivateDomainExtractor.getInstance(),

View File

@ -84,28 +84,6 @@ import org.sqlite.SQLiteJDBCLoader;
*/
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());
static {
@ -142,14 +120,12 @@ public class EventDB {
private final String dbPath;
private PreparedStatement getDBInfoStmt;
private PreparedStatement getEventByIDStmt;
private PreparedStatement getMaxTimeStmt;
private PreparedStatement getMinTimeStmt;
private PreparedStatement getDataSourceIDsStmt;
private PreparedStatement getHashSetNamesStmt;
private PreparedStatement insertRowStmt;
private PreparedStatement recordDBInfoStmt;
private PreparedStatement insertHashSetStmt;
private PreparedStatement insertHashHitStmt;
private PreparedStatement insertTagStmt;
@ -394,14 +370,6 @@ public class EventDB {
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
* value for the datasource_id column in the events table.
@ -489,10 +457,6 @@ public class EventDB {
return -1l;
}
boolean getWasIngestRunning() {
return getDBInfo(DBInfoKey.WAS_INGEST_RUNNING, 0) != 0;
}
/**
* 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
getMinTimeStmt = prepareStatement("SELECT Min(time) AS min FROM events"); // 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
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
@ -938,18 +900,6 @@ public class EventDB {
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) {
trans.rollback();
}
@ -983,8 +933,7 @@ public class EventDB {
try {
LOGGER.log(Level.INFO, String.format("sqlite-jdbc version %s loaded in %s mode", // NON-NLS
SQLiteJDBCLoader.getVersion(), SQLiteJDBCLoader.isNativeMode()
? "native" : "pure-java")); // NON-NLS
SQLiteJDBCLoader.getVersion(), SQLiteJDBCLoader.isNativeMode() ? "native" : "pure-java")); // NON-NLS
} catch (Exception exception) {
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
}
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 {
PreparedStatement prepareStatement = con.prepareStatement(queryString);
@ -1249,20 +1176,6 @@ public class EventDB {
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
*/

View File

@ -35,6 +35,7 @@ import java.util.concurrent.ExecutionException;
import java.util.concurrent.Executor;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
import java.util.function.Consumer;
import java.util.logging.Level;
import java.util.stream.Collectors;
import javafx.application.Platform;
@ -44,6 +45,7 @@ import javafx.beans.property.ReadOnlyObjectProperty;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.collections.ObservableMap;
import javafx.concurrent.Worker;
import javax.swing.JOptionPane;
import org.apache.commons.lang3.StringUtils;
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.coreutils.Logger;
import org.sleuthkit.autopsy.coreutils.ThreadConfined;
import org.sleuthkit.autopsy.ingest.IngestManager;
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.FilteredEventsModel;
import org.sleuthkit.autopsy.timeline.datamodel.TimeLineEvent;
@ -168,7 +168,7 @@ public class EventsRepository {
*/
public Long getMaxTime() {
return maxCache.getUnchecked("max"); // NON-NLS
// return eventDB.getMaxTime();
}
/**
@ -176,31 +176,7 @@ public class EventsRepository {
*/
public Long getMinTime() {
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) {
@ -227,6 +203,10 @@ public class EventsRepository {
return eventCountsCache.getUnchecked(params);
}
synchronized public int countAllEvents() {
return eventDB.countAllEvents();
}
private void invalidateCaches() {
minCache.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) {
return SQLHelper.getSQLWhere(f1).equals(SQLHelper.getSQLWhere(f2));
}
@ -352,27 +320,56 @@ public class EventsRepository {
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)
public CancellationProgressTask<Void> rebuildRepository() {
return rebuildRepository(DBPopulationMode.FULL);
}
@ThreadConfined(type = ThreadConfined.ThreadType.JFX)
public CancellationProgressTask<Void> rebuildTags() {
return rebuildRepository(DBPopulationMode.TAGS_ONLY);
public CancellationProgressTask<Void> rebuildRepository(Consumer<Worker.State> onStateChange) {
return rebuildRepository(DBPopulationMode.FULL, onStateChange);
}
/**
*
* @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)
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
if (dbWorker != null) {
dbWorker.cancel();
}
dbWorker = new DBPopulationWorker(mode);
dbWorker = new DBPopulationWorker(mode, onStateChange);
workerExecutor.execute(dbWorker);
return dbWorker;
}
@ -437,10 +434,11 @@ public class EventsRepository {
}
}
DBPopulationWorker(DBPopulationMode mode) {
DBPopulationWorker(DBPopulationMode mode, Consumer<Worker.State> onStateChange) {
skCase = autoCase.getSleuthkitCase();
tagsManager = autoCase.getServices().getTagsManager();
this.dbPopulationMode = mode;
this.stateProperty().addListener(stateObservable -> onStateChange.accept(getState()));
}
void restartProgressHandle(String title, String message, Double workDone, double total, Boolean cancellable) {
@ -470,11 +468,6 @@ public class EventsRepository {
protected Void call() throws Exception {
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) {
//drop old db, and add back MAC and artifact events
LOGGER.log(Level.INFO, "Beginning population of timeline db."); // NON-NLS
@ -513,9 +506,6 @@ public class EventsRepository {
Platform.runLater(() -> cancellable.set(false));
restartProgressHandle(Bundle.progressWindow_msg_commitingDb(), "", -1D, 1, false);
eventDB.commitTransaction(trans);
if (isCancelRequested() == false) {
recordDBPopulationState(lastObjId, lastArtfID, injestRunning);
}
eventDB.analyze();
populateFilterData(skCase);

View File

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

View File

@ -67,6 +67,13 @@ public abstract class CompoundFilter<SubFilterType extends Filter> extends Abstr
}
});
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) {

View File

@ -21,6 +21,7 @@ package org.sleuthkit.autopsy.timeline.filters;
import java.util.Comparator;
import java.util.stream.Collectors;
import javafx.beans.binding.Bindings;
import javafx.beans.value.ObservableBooleanValue;
import org.openide.util.NbBundle;
/**
@ -29,7 +30,6 @@ import org.openide.util.NbBundle;
public class DataSourcesFilter extends UnionFilter<DataSourceFilter> {
public DataSourcesFilter() {
getDisabledProperty().bind(Bindings.size(getSubFilters()).lessThanOrEqualTo(1));
setSelected(false);
}
@ -69,7 +69,6 @@ public class DataSourcesFilter extends UnionFilter<DataSourceFilter> {
.map(DataSourceFilter::getDataSourceID)
.filter(t -> t == dataSourceFilter.getDataSourceID())
.findAny().isPresent() == false) {
dataSourceFilter.getDisabledProperty().bind(getDisabledProperty());
getSubFilters().add(dataSourceFilter);
getSubFilters().sort(Comparator.comparing(DataSourceFilter::getDisplayName));
}
@ -100,4 +99,10 @@ public class DataSourcesFilter extends UnionFilter<DataSourceFilter> {
public int hashCode() {
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.property.SimpleBooleanProperty;
import javafx.beans.value.ObservableBooleanValue;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
@ -77,7 +78,7 @@ public interface Filter {
*/
void setDisabled(Boolean act);
SimpleBooleanProperty getDisabledProperty();
ObservableBooleanValue disabledProperty();
boolean isDisabled();

View File

@ -8,6 +8,7 @@ package org.sleuthkit.autopsy.timeline.filters;
import java.util.Comparator;
import java.util.stream.Collectors;
import javafx.beans.binding.Bindings;
import javafx.beans.value.ObservableBooleanValue;
import org.openide.util.NbBundle;
/**
@ -16,13 +17,12 @@ import org.openide.util.NbBundle;
public class HashHitsFilter extends UnionFilter<HashSetFilter> {
@Override
@NbBundle.Messages("hashHitsFilter.displayName.text=Only Hash Set Hits")
@NbBundle.Messages("hashHitsFilter.displayName.text=Hash Sets")
public String getDisplayName() {
return Bundle.hashHitsFilter_displayName_text();
}
public HashHitsFilter() {
getDisabledProperty().bind(Bindings.size(getSubFilters()).lessThan(1));
setSelected(false);
}
@ -81,4 +81,9 @@ public class HashHitsFilter extends UnionFilter<HashSetFilter> {
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.stream.Collectors;
import javafx.beans.binding.BooleanBinding;
import javafx.collections.FXCollections;
/**
@ -70,7 +71,7 @@ public class RootFilter extends IntersectionFilter<Filter> {
public RootFilter copyOf() {
Set<Filter> annonymousSubFilters = getSubFilters().stream()
.filter(subFilter ->
!(subFilter.equals(knownFilter)
!(subFilter.equals(knownFilter)
|| subFilter.equals(tagsFilter)
|| subFilter.equals(hashFilter)
|| subFilter.equals(typeFilter)
@ -108,4 +109,17 @@ public class RootFilter extends IntersectionFilter<Filter> {
}
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.stream.Collectors;
import javafx.beans.binding.Bindings;
import javafx.beans.value.ObservableBooleanValue;
import org.openide.util.NbBundle;
import org.sleuthkit.datamodel.TagName;
@ -17,13 +18,12 @@ import org.sleuthkit.datamodel.TagName;
public class TagsFilter extends UnionFilter<TagNameFilter> {
@Override
@NbBundle.Messages("tagsFilter.displayName.text=Only Events Tagged")
@NbBundle.Messages("tagsFilter.displayName.text=Tags")
public String getDisplayName() {
return Bundle.tagsFilter_displayName_text();
}
public TagsFilter() {
getDisabledProperty().bind(Bindings.size(getSubFilters()).lessThan(1));
setSelected(false);
}
@ -89,5 +89,8 @@ public class TagsFilter extends UnionFilter<TagNameFilter> {
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
@NbBundle.Messages("TypeFilter.displayName.text=Event Type Filter")
@NbBundle.Messages("TypeFilter.displayName.text=Event Type")
public String getDisplayName() {
return (eventType == RootEventType.getInstance())
? Bundle.TypeFilter_displayName_text()

View File

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

View File

@ -347,9 +347,9 @@ final public class VisualizationPanel extends BorderPane {
refreshTimeUI(); //populate the viz
//this should use an event(EventBus) , not this weird observable pattern
controller.getNeedsHistogramRebuild().addListener((observable, oldValue, newValue) -> {
if (newValue) {
refreshHistorgram();
controller.eventsDBStaleProperty().addListener(staleProperty -> {
if (controller.isEventsDBStale()) {
Platform.runLater(VisualizationPanel.this::refreshHistorgram);
}
});
refreshHistorgram();
@ -569,7 +569,7 @@ final public class VisualizationPanel extends BorderPane {
titledPane.setText(Bundle.NoEventsDialog_titledPane_text());
noEventsDialogLabel.setText(NbBundle.getMessage(NoEventsDialog.class, "VisualizationPanel.noEventsDialogLabel.text")); // NON-NLS
dismissButton.setOnAction(actionEvent -> closeCallback.run());
ActionUtils.configureButton(new ZoomToEvents(controller), zoomButton);

View File

@ -20,6 +20,7 @@ package org.sleuthkit.autopsy.timeline.ui.filtering;
import java.util.function.Supplier;
import javafx.beans.property.SimpleBooleanProperty;
import javafx.beans.value.ObservableBooleanValue;
import javafx.scene.control.CheckBox;
import javafx.scene.control.IndexedCell;
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 SimpleBooleanProperty selectedProperty;
private SimpleBooleanProperty disabledProperty;
private ObservableBooleanValue disabledProperty;
@Override
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);
}
if (disabledProperty != null) {
checkBox.disableProperty().unbindBidirectional(disabledProperty);
checkBox.disableProperty().unbind();//disabledProperty);
}
if (item == null) {
cell.setText(null);
cell.setGraphic(null);
} else {
cell.setText(item.getDisplayName());
checkBox.setText(item.getDisplayName());
selectedProperty = item.selectedProperty();
checkBox.selectedProperty().bindBidirectional(selectedProperty);
disabledProperty = item.getDisabledProperty();
checkBox.disableProperty().bindBidirectional(disabledProperty);
disabledProperty = item.disabledProperty();
checkBox.disableProperty().bind(disabledProperty);
cell.setGraphic(checkBox);
}
}

View File

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

View File

@ -1,5 +1,5 @@
Manifest-Version: 1.0
OpenIDE-Module: org.sleuthkit.autopsy.imagegallery/1
OpenIDE-Module-Implementation-Version: 1
OpenIDE-Module: org.sleuthkit.autopsy.imagegallery/2
OpenIDE-Module-Implementation-Version: 2
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.needs.restart=true
project.license=imagegallery
spec.version.base=1.0
spec.version.base=2.0

View File

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

View File

@ -23,16 +23,16 @@ import java.util.Arrays;
import java.util.Collections;
import java.util.HashSet;
import static java.util.Objects.isNull;
import java.util.Optional;
import java.util.Set;
import java.util.logging.Level;
import java.util.stream.Collectors;
import java.util.stream.Stream;
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.modules.filetypeid.FileTypeDetector;
import org.sleuthkit.datamodel.AbstractFile;
import org.sleuthkit.datamodel.Content;
import org.sleuthkit.datamodel.TskCoreException;
/**
@ -149,13 +149,13 @@ public enum FileTypeUtils {
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)) {
try {
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
}
FILE_TYPE_DETECTOR = new FileTypeDetector();
}
return FILE_TYPE_DETECTOR;
}
@ -169,24 +169,12 @@ public enum FileTypeUtils {
*
* @return true if this file is supported or false if not
*/
public static boolean isDrawable(AbstractFile file) throws TskCoreException {
return hasDrawableMimeType(file).orElseGet(() -> {
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());
public static boolean isDrawable(AbstractFile file) throws TskCoreException, FileTypeDetector.FileTypeDetectorInitException {
return hasDrawableMIMEType(file);
}
static boolean isDrawableMimeType(String mimeType) {
if (isNull(mimeType)) {
if (StringUtils.isBlank(mimeType)) {
return false;
} else {
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
*
* @param file
@ -205,8 +197,9 @@ public enum FileTypeUtils {
* type. False if a non image/video mimetype. empty Optional if a
* mimetype could not be detected.
*/
static Optional<Boolean> hasDrawableMimeType(AbstractFile file) throws TskCoreException {
return getMimeType(file).map(FileTypeUtils::isDrawableMimeType);
static boolean hasDrawableMIMEType(AbstractFile file) throws TskCoreException, FileTypeDetector.FileTypeDetectorInitException {
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
* available, a video extension.
*/
public static boolean isVideoFile(AbstractFile file) {
public static boolean hasVideoMIMEType(AbstractFile file) {
try {
return getMimeType(file)
.map(String::toLowerCase)
.map(mimeType
-> mimeType.startsWith("video/")
|| videoMimeTypes.contains(mimeType))
.orElseGet(() -> FileTypeUtils.videoExtensions.contains(file.getNameExtension()));
} catch (TskCoreException ex) {
return FileTypeUtils.videoExtensions.contains(file.getNameExtension());
String mimeType = getFileTypeDetector().detect(file).toLowerCase();
return mimeType.startsWith("video/") || videoMimeTypes.contains(mimeType);
} catch (FileTypeDetector.FileTypeDetectorInitException | TskCoreException ex) {
LOGGER.log(Level.SEVERE, "Error determining MIME type of " + getContentPathSafe(file), ex);
return false;
}
}
/**
* 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.PropertyChangeListener;
import java.util.Collections;
import java.util.List;
import java.util.Objects;
import java.util.Optional;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.Executor;
import java.util.concurrent.Executors;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.logging.Level;
import java.util.stream.Collectors;
import javafx.application.Platform;
import javafx.beans.Observable;
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.Toolbar;
import org.sleuthkit.autopsy.ingest.IngestManager;
import org.sleuthkit.autopsy.modules.filetypeid.FileTypeDetector;
import org.sleuthkit.datamodel.AbstractFile;
import org.sleuthkit.datamodel.Content;
import org.sleuthkit.datamodel.FileSystem;
import org.sleuthkit.datamodel.Image;
import org.sleuthkit.datamodel.SleuthkitCase;
import org.sleuthkit.datamodel.TskCoreException;
import org.sleuthkit.datamodel.TskData;
import org.sleuthkit.datamodel.VirtualDirectory;
/**
* Connects different parts of ImageGallery together and is hub for flow of
@ -853,23 +848,15 @@ public final class ImageGalleryController implements Executor {
if (known) {
taskDB.removeFile(f.getId(), tr); //remove known files
} else {
Optional<String> mimeType = FileTypeUtils.getMimeType(f);
if (mimeType.isPresent()) {
//mime type
if (FileTypeUtils.isDrawableMimeType(mimeType.get())) { //supported mimetype => analyzed
try {
if (FileTypeUtils.hasDrawableMIMEType(f)) { //supported mimetype => analyzed
taskDB.updateFile(DrawableFile.create(f, true, false), tr);
} else { //unsupported mimtype => analyzed but shouldn't include
taskDB.removeFile(f.getId(), tr);
}
} else {
//no mime tyoe
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);
}
} catch (FileTypeDetector.FileTypeDetectorInitException ex) {
throw new RuntimeException(ex);
}
}
}
@ -916,37 +903,8 @@ public final class ImageGalleryController implements Executor {
@Override
List<AbstractFile> getFiles() throws TskCoreException {
if (dataSource instanceof Image) {
List<FileSystem> fileSystems = ((Image) dataSource).getFileSystems();
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);
}
long datasourceID = dataSource.getDataSource().getId();
return tskCase.findAllFilesWhere("data_source_obj_id = " + datasourceID + " AND " + DRAWABLE_QUERY);
}
@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
queueDBWorkerTask(new RemoveFileTask(file, db));
}
} catch (TskCoreException ex) {
} catch (TskCoreException | FileTypeDetector.FileTypeDetectorInitException ex) {
//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
throw new RuntimeException(ex);
LOGGER.log(Level.SEVERE, "Unable to determine if file is drawable and not known. Not making any changes to DB", ex); //NON-NLS
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

View File

@ -22,11 +22,11 @@ import java.nio.file.Path;
import java.nio.file.Paths;
import org.apache.commons.lang3.StringUtils;
import static org.apache.commons.lang3.StringUtils.isNotBlank;
import org.openide.util.NbBundle;
import org.sleuthkit.autopsy.casemodule.Case;
import org.sleuthkit.autopsy.coreutils.Logger;
import org.sleuthkit.autopsy.imagegallery.datamodel.DrawableDB;
import org.sleuthkit.autopsy.modules.filetypeid.FileTypeDetector;
import org.sleuthkit.datamodel.AbstractFile;
import org.sleuthkit.datamodel.TskCoreException;
import org.sleuthkit.datamodel.TskData;
@ -105,7 +105,7 @@ public class ImageGalleryModule {
* @return true if the given {@link AbstractFile} is "drawable" and not
* '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);
}
}

View File

@ -126,7 +126,7 @@ public enum ThumbnailCache {
*/
private Image load(DrawableFile file) {
if (FileTypeUtils.isGIF(file.getAbstractFile())) {
if (ImageUtils.isGIF(file.getAbstractFile())) {
//directly read gif to preserve potential animation,
//NOTE: not saved to disk!
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) {
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, ",") + " )";
//count the fileids that are in the given list and don't have a non-zero category assigned to them.
String name
= "SELECT COUNT(obj_id) FROM tsk_files where obj_id IN " + fileIdsList //NON-NLS
String name =
"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
try (SleuthkitCase.CaseDbQuery executeQuery = controller.getSleuthKitCase().executeQuery(name);
ResultSet resultSet = executeQuery.getResultSet();) {

View File

@ -60,7 +60,7 @@ public abstract class DrawableFile {
private static final Logger LOGGER = Logger.getLogger(DrawableFile.class.getName());
public static DrawableFile create(AbstractFile abstractFileById, boolean analyzed) {
return create(abstractFileById, analyzed, FileTypeUtils.isVideoFile(abstractFileById));
return create(abstractFileById, analyzed, FileTypeUtils.hasVideoMIMEType(abstractFileById));
}
/**

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