mirror of
https://github.com/overcuriousity/autopsy-flatpak.git
synced 2025-07-06 21:00:22 +00:00
Merge branch 'master' of github.com:sleuthkit/autopsy
This commit is contained in:
commit
dc0f15c2e2
@ -1,4 +1,4 @@
|
|||||||
<?xml version="1.1" encoding="UTF-8" ?>
|
<?xml version="1.0" encoding="UTF-8" ?>
|
||||||
|
|
||||||
<Form version="1.5" maxVersion="1.7" type="org.netbeans.modules.form.forminfo.JPanelFormInfo">
|
<Form version="1.5" maxVersion="1.7" type="org.netbeans.modules.form.forminfo.JPanelFormInfo">
|
||||||
<AuxValues>
|
<AuxValues>
|
||||||
@ -20,7 +20,7 @@
|
|||||||
<Group type="102" alignment="0" attributes="0">
|
<Group type="102" alignment="0" attributes="0">
|
||||||
<Component id="pauseButton" min="-2" max="-2" attributes="0"/>
|
<Component id="pauseButton" min="-2" max="-2" attributes="0"/>
|
||||||
<EmptySpace max="-2" attributes="0"/>
|
<EmptySpace max="-2" attributes="0"/>
|
||||||
<Component id="progressSlider" pref="160" max="32767" attributes="0"/>
|
<Component id="progressSlider" pref="158" max="32767" attributes="0"/>
|
||||||
<EmptySpace max="-2" attributes="0"/>
|
<EmptySpace max="-2" attributes="0"/>
|
||||||
<Component id="progressLabel" min="-2" max="-2" attributes="0"/>
|
<Component id="progressLabel" min="-2" max="-2" attributes="0"/>
|
||||||
<EmptySpace max="-2" attributes="0"/>
|
<EmptySpace max="-2" attributes="0"/>
|
||||||
@ -32,10 +32,10 @@
|
|||||||
<Group type="102" alignment="1" attributes="0">
|
<Group type="102" alignment="1" attributes="0">
|
||||||
<Component id="videoPanel" max="32767" attributes="0"/>
|
<Component id="videoPanel" max="32767" attributes="0"/>
|
||||||
<EmptySpace max="-2" attributes="0"/>
|
<EmptySpace max="-2" attributes="0"/>
|
||||||
<Group type="103" groupAlignment="1" attributes="0">
|
<Group type="103" groupAlignment="1" max="-2" attributes="0">
|
||||||
<Component id="pauseButton" min="-2" max="-2" attributes="0"/>
|
<Component id="pauseButton" max="32767" attributes="0"/>
|
||||||
<Component id="progressLabel" min="-2" max="-2" attributes="0"/>
|
<Component id="progressSlider" max="32767" attributes="0"/>
|
||||||
<Component id="progressSlider" min="-2" max="-2" attributes="0"/>
|
<Component id="progressLabel" alignment="1" max="32767" attributes="0"/>
|
||||||
</Group>
|
</Group>
|
||||||
</Group>
|
</Group>
|
||||||
</Group>
|
</Group>
|
||||||
@ -47,6 +47,15 @@
|
|||||||
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||||
<ResourceString bundle="org/sleuthkit/autopsy/corecomponents/Bundle.properties" key="DataContentViewerMedia.pauseButton.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
<ResourceString bundle="org/sleuthkit/autopsy/corecomponents/Bundle.properties" key="DataContentViewerMedia.pauseButton.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||||
</Property>
|
</Property>
|
||||||
|
<Property name="maximumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
|
||||||
|
<Dimension value="[45, 23]"/>
|
||||||
|
</Property>
|
||||||
|
<Property name="minimumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
|
||||||
|
<Dimension value="[45, 23]"/>
|
||||||
|
</Property>
|
||||||
|
<Property name="preferredSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
|
||||||
|
<Dimension value="[45, 23]"/>
|
||||||
|
</Property>
|
||||||
</Properties>
|
</Properties>
|
||||||
<Events>
|
<Events>
|
||||||
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="pauseButtonActionPerformed"/>
|
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="pauseButtonActionPerformed"/>
|
||||||
@ -68,6 +77,9 @@
|
|||||||
</Layout>
|
</Layout>
|
||||||
</Container>
|
</Container>
|
||||||
<Component class="javax.swing.JSlider" name="progressSlider">
|
<Component class="javax.swing.JSlider" name="progressSlider">
|
||||||
|
<Properties>
|
||||||
|
<Property name="value" type="int" value="0"/>
|
||||||
|
</Properties>
|
||||||
</Component>
|
</Component>
|
||||||
<Component class="javax.swing.JLabel" name="progressLabel">
|
<Component class="javax.swing.JLabel" name="progressLabel">
|
||||||
<Properties>
|
<Properties>
|
||||||
|
@ -21,6 +21,7 @@ package org.sleuthkit.autopsy.corecomponents;
|
|||||||
import java.awt.Component;
|
import java.awt.Component;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
|
import java.util.concurrent.CancellationException;
|
||||||
import java.util.logging.Level;
|
import java.util.logging.Level;
|
||||||
import java.util.logging.Logger;
|
import java.util.logging.Logger;
|
||||||
import javax.swing.BoxLayout;
|
import javax.swing.BoxLayout;
|
||||||
@ -45,18 +46,20 @@ import org.sleuthkit.datamodel.TskData;
|
|||||||
*
|
*
|
||||||
* @author dfickling
|
* @author dfickling
|
||||||
*/
|
*/
|
||||||
@ServiceProvider(service = DataContentViewer.class, position=5)
|
@ServiceProvider(service = DataContentViewer.class, position = 5)
|
||||||
public class DataContentViewerMedia extends javax.swing.JPanel implements DataContentViewer {
|
public class DataContentViewerMedia extends javax.swing.JPanel implements DataContentViewer {
|
||||||
|
|
||||||
private static final String[] IMAGES = new String[]{ ".jpg", ".jpeg", ".png", ".gif", ".jpe", ".bmp"};
|
private static final String[] IMAGES = new String[]{".jpg", ".jpeg", ".png", ".gif", ".jpe", ".bmp"};
|
||||||
private static final String[] VIDEOS = new String[]{ ".mov", ".m4v", ".flv", ".mp4", ".3gp", ".avi", ".mpg", ".mpeg"};
|
private static final String[] VIDEOS = new String[]{".mov", ".m4v", ".flv", ".mp4", ".3gp", ".avi", ".mpg", ".mpeg"};
|
||||||
private static final String[] AUDIOS = new String[]{ ".mp3", ".wav", ".wma"};
|
private static final String[] AUDIOS = new String[]{".mp3", ".wav", ".wma"};
|
||||||
private static final Logger logger = Logger.getLogger(DataContentViewerMedia.class.getName());
|
private static final Logger logger = Logger.getLogger(DataContentViewerMedia.class.getName());
|
||||||
private VideoComponent videoComponent;
|
private VideoComponent videoComponent;
|
||||||
private PlayBin2 playbin2;
|
private PlayBin2 playbin2;
|
||||||
private File currentFile;
|
private File currentFile;
|
||||||
private long durationMillis = 0;
|
private long durationMillis = 0;
|
||||||
private boolean autoTracking = false; // true if the slider is moving automatically
|
private boolean autoTracking = false; // true if the slider is moving automatically
|
||||||
|
private final Object playbinLock = new Object(); // lock for synchronization of playbin2 player
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates new form DataContentViewerVideo
|
* Creates new form DataContentViewerVideo
|
||||||
*/
|
*/
|
||||||
@ -68,19 +71,23 @@ public class DataContentViewerMedia extends javax.swing.JPanel implements DataCo
|
|||||||
private void customizeComponents() {
|
private void customizeComponents() {
|
||||||
Gst.init();
|
Gst.init();
|
||||||
progressSlider.addChangeListener(new ChangeListener() {
|
progressSlider.addChangeListener(new ChangeListener() {
|
||||||
|
/**
|
||||||
|
* Should always try to synchronize any call to
|
||||||
|
* progressSlider.setValue() to avoid a different thread changing
|
||||||
|
* playbin while stateChanged() is processing
|
||||||
|
*/
|
||||||
@Override
|
@Override
|
||||||
public void stateChanged(ChangeEvent e) {
|
public void stateChanged(ChangeEvent e) {
|
||||||
int time = progressSlider.getValue();
|
int time = progressSlider.getValue();
|
||||||
if(playbin2 != null && !autoTracking) {
|
synchronized (playbinLock) {
|
||||||
|
if (playbin2 != null && !autoTracking) {
|
||||||
State orig = playbin2.getState();
|
State orig = playbin2.getState();
|
||||||
playbin2.pause();
|
playbin2.pause();
|
||||||
playbin2.getState();
|
|
||||||
playbin2.seek(ClockTime.fromMillis(time));
|
playbin2.seek(ClockTime.fromMillis(time));
|
||||||
playbin2.setState(orig);
|
playbin2.setState(orig);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -99,6 +106,9 @@ public class DataContentViewerMedia extends javax.swing.JPanel implements DataCo
|
|||||||
progressLabel = new javax.swing.JLabel();
|
progressLabel = new javax.swing.JLabel();
|
||||||
|
|
||||||
pauseButton.setText(org.openide.util.NbBundle.getMessage(DataContentViewerMedia.class, "DataContentViewerMedia.pauseButton.text")); // NOI18N
|
pauseButton.setText(org.openide.util.NbBundle.getMessage(DataContentViewerMedia.class, "DataContentViewerMedia.pauseButton.text")); // NOI18N
|
||||||
|
pauseButton.setMaximumSize(new java.awt.Dimension(45, 23));
|
||||||
|
pauseButton.setMinimumSize(new java.awt.Dimension(45, 23));
|
||||||
|
pauseButton.setPreferredSize(new java.awt.Dimension(45, 23));
|
||||||
pauseButton.addActionListener(new java.awt.event.ActionListener() {
|
pauseButton.addActionListener(new java.awt.event.ActionListener() {
|
||||||
public void actionPerformed(java.awt.event.ActionEvent evt) {
|
public void actionPerformed(java.awt.event.ActionEvent evt) {
|
||||||
pauseButtonActionPerformed(evt);
|
pauseButtonActionPerformed(evt);
|
||||||
@ -116,6 +126,8 @@ public class DataContentViewerMedia extends javax.swing.JPanel implements DataCo
|
|||||||
.addGap(0, 242, Short.MAX_VALUE)
|
.addGap(0, 242, Short.MAX_VALUE)
|
||||||
);
|
);
|
||||||
|
|
||||||
|
progressSlider.setValue(0);
|
||||||
|
|
||||||
progressLabel.setText(org.openide.util.NbBundle.getMessage(DataContentViewerMedia.class, "DataContentViewerMedia.progressLabel.text")); // NOI18N
|
progressLabel.setText(org.openide.util.NbBundle.getMessage(DataContentViewerMedia.class, "DataContentViewerMedia.progressLabel.text")); // NOI18N
|
||||||
|
|
||||||
javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
|
javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
|
||||||
@ -124,9 +136,9 @@ public class DataContentViewerMedia extends javax.swing.JPanel implements DataCo
|
|||||||
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||||
.addComponent(videoPanel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
|
.addComponent(videoPanel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
|
||||||
.addGroup(layout.createSequentialGroup()
|
.addGroup(layout.createSequentialGroup()
|
||||||
.addComponent(pauseButton)
|
.addComponent(pauseButton, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
|
||||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||||
.addComponent(progressSlider, javax.swing.GroupLayout.DEFAULT_SIZE, 160, Short.MAX_VALUE)
|
.addComponent(progressSlider, javax.swing.GroupLayout.DEFAULT_SIZE, 158, Short.MAX_VALUE)
|
||||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||||
.addComponent(progressLabel)
|
.addComponent(progressLabel)
|
||||||
.addContainerGap())
|
.addContainerGap())
|
||||||
@ -136,26 +148,30 @@ public class DataContentViewerMedia extends javax.swing.JPanel implements DataCo
|
|||||||
.addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
|
.addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
|
||||||
.addComponent(videoPanel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
|
.addComponent(videoPanel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
|
||||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||||
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING)
|
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING, false)
|
||||||
.addComponent(pauseButton)
|
.addComponent(pauseButton, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
|
||||||
.addComponent(progressLabel)
|
.addComponent(progressSlider, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
|
||||||
.addComponent(progressSlider, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)))
|
.addComponent(progressLabel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)))
|
||||||
);
|
);
|
||||||
}// </editor-fold>//GEN-END:initComponents
|
}// </editor-fold>//GEN-END:initComponents
|
||||||
|
|
||||||
private void pauseButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_pauseButtonActionPerformed
|
private void pauseButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_pauseButtonActionPerformed
|
||||||
if(playbin2.getState().equals(State.PLAYING)){
|
synchronized (playbinLock) {
|
||||||
|
State state = playbin2.getState();
|
||||||
|
if (state.equals(State.PLAYING)) {
|
||||||
playbin2.pause();
|
playbin2.pause();
|
||||||
pauseButton.setText("►");
|
pauseButton.setText("►");
|
||||||
} else if(playbin2.getState().equals(State.PAUSED)) {
|
playbin2.setState(State.PAUSED);
|
||||||
|
} else if (state.equals(State.PAUSED)) {
|
||||||
playbin2.play();
|
playbin2.play();
|
||||||
pauseButton.setText("||");
|
pauseButton.setText("||");
|
||||||
} else {
|
playbin2.setState(State.PLAYING);
|
||||||
|
} else if (state.equals(State.READY)) {
|
||||||
ExtractMedia em = new ExtractMedia(currentFile, getJFile(currentFile));
|
ExtractMedia em = new ExtractMedia(currentFile, getJFile(currentFile));
|
||||||
em.execute();
|
em.execute();
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}//GEN-LAST:event_pauseButtonActionPerformed
|
}//GEN-LAST:event_pauseButtonActionPerformed
|
||||||
|
|
||||||
// Variables declaration - do not modify//GEN-BEGIN:variables
|
// Variables declaration - do not modify//GEN-BEGIN:variables
|
||||||
private javax.swing.JButton pauseButton;
|
private javax.swing.JButton pauseButton;
|
||||||
private javax.swing.JLabel progressLabel;
|
private javax.swing.JLabel progressLabel;
|
||||||
@ -165,32 +181,31 @@ public class DataContentViewerMedia extends javax.swing.JPanel implements DataCo
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setNode(Node selectedNode) {
|
public void setNode(Node selectedNode) {
|
||||||
pauseButton.setText("►");
|
reset();
|
||||||
if(selectedNode == null) {
|
|
||||||
setDataView(null);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
File file = selectedNode.getLookup().lookup(File.class);
|
|
||||||
setDataView(file);
|
|
||||||
if(file == null) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
boolean isVidOrAud = containsExt(file.getName(), VIDEOS) || containsExt(file.getName(), AUDIOS);
|
|
||||||
pauseButton.setVisible(isVidOrAud);
|
|
||||||
progressLabel.setVisible(isVidOrAud);
|
|
||||||
progressSlider.setVisible(isVidOrAud);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void setDataView(File file) {
|
|
||||||
if(file == null) {
|
|
||||||
setComponentsVisibility(false);
|
setComponentsVisibility(false);
|
||||||
|
if (selectedNode == null) {
|
||||||
return;
|
return;
|
||||||
} else {
|
|
||||||
setComponentsVisibility(true);
|
|
||||||
}
|
}
|
||||||
this.currentFile = file;
|
|
||||||
|
|
||||||
|
File file = selectedNode.getLookup().lookup(File.class);
|
||||||
|
if (file == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
currentFile = file;
|
||||||
if (containsExt(file.getName(), IMAGES)) {
|
if (containsExt(file.getName(), IMAGES)) {
|
||||||
|
showImage(file);
|
||||||
|
} else if (containsExt(file.getName(), VIDEOS) || containsExt(file.getName(), AUDIOS)) {
|
||||||
|
setupVideo(file);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initialize vars and display the image on the panel.
|
||||||
|
*
|
||||||
|
* @param file
|
||||||
|
*/
|
||||||
|
private void showImage(File file) {
|
||||||
java.io.File ioFile = getJFile(file);
|
java.io.File ioFile = getJFile(file);
|
||||||
if (!ioFile.exists()) {
|
if (!ioFile.exists()) {
|
||||||
try {
|
try {
|
||||||
@ -199,10 +214,56 @@ public class DataContentViewerMedia extends javax.swing.JPanel implements DataCo
|
|||||||
logger.log(Level.WARNING, "Error buffering file", ex);
|
logger.log(Level.WARNING, "Error buffering file", ex);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
videoComponent = new VideoComponent();
|
||||||
|
synchronized (playbinLock) {
|
||||||
|
playbin2 = new PlayBin2("ImageViewer");
|
||||||
|
playbin2.setVideoSink(videoComponent.getElement());
|
||||||
|
}
|
||||||
|
|
||||||
|
videoPanel.removeAll();
|
||||||
|
videoPanel.setLayout(new BoxLayout(videoPanel, BoxLayout.Y_AXIS));
|
||||||
|
videoPanel.add(videoComponent);
|
||||||
|
videoPanel.revalidate();
|
||||||
|
videoPanel.repaint();
|
||||||
|
|
||||||
|
synchronized (playbinLock) {
|
||||||
playbin2.setInputFile(ioFile);
|
playbin2.setInputFile(ioFile);
|
||||||
playbin2.play();
|
playbin2.play();
|
||||||
}
|
}
|
||||||
|
videoPanel.setVisible(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initialize all the necessary vars to play a video/audio file.
|
||||||
|
*
|
||||||
|
* @param file the File to play
|
||||||
|
*/
|
||||||
|
private void setupVideo(File file) {
|
||||||
|
java.io.File ioFile = getJFile(file);
|
||||||
|
|
||||||
|
pauseButton.setText("►");
|
||||||
|
progressSlider.setValue(0);
|
||||||
|
|
||||||
|
videoComponent = new VideoComponent();
|
||||||
|
synchronized (playbinLock) {
|
||||||
|
playbin2 = new PlayBin2("VideoPlayer");
|
||||||
|
playbin2.setVideoSink(videoComponent.getElement());
|
||||||
|
}
|
||||||
|
|
||||||
|
videoPanel.removeAll();
|
||||||
|
videoPanel.setLayout(new BoxLayout(videoPanel, BoxLayout.Y_AXIS));
|
||||||
|
videoPanel.add(videoComponent);
|
||||||
|
videoPanel.revalidate();
|
||||||
|
videoPanel.repaint();
|
||||||
|
|
||||||
|
synchronized (playbinLock) {
|
||||||
|
playbin2.setInputFile(ioFile);
|
||||||
|
playbin2.setState(State.READY);
|
||||||
|
}
|
||||||
|
setComponentsVisibility(true);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* To set the visibility of specific components in this class.
|
* To set the visibility of specific components in this class.
|
||||||
*
|
*
|
||||||
@ -237,42 +298,31 @@ public class DataContentViewerMedia extends javax.swing.JPanel implements DataCo
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void resetComponent() {
|
public void resetComponent() {
|
||||||
|
// we don't want this to do anything
|
||||||
|
// because we already reset on each selected node
|
||||||
}
|
}
|
||||||
|
|
||||||
private void resetVideo() {
|
private void reset() {
|
||||||
if(playbin2 != null) {
|
synchronized (playbinLock) {
|
||||||
if(playbin2.isPlaying()) {
|
if (playbin2 != null) {
|
||||||
|
if (playbin2.isPlaying()) {
|
||||||
playbin2.stop();
|
playbin2.stop();
|
||||||
}
|
}
|
||||||
playbin2.setState(State.NULL);
|
playbin2.setState(State.NULL);
|
||||||
if(playbin2.getState() == State.NULL) {
|
// try {
|
||||||
|
// Thread.sleep(20); // gstreamer needs to catch up
|
||||||
|
// } catch (InterruptedException ex) { }
|
||||||
|
if (playbin2.getState().equals(State.NULL)) {
|
||||||
playbin2.dispose();
|
playbin2.dispose();
|
||||||
}
|
}
|
||||||
playbin2 = null;
|
playbin2 = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
videoComponent = null;
|
videoComponent = null;
|
||||||
|
|
||||||
playbin2 = new PlayBin2("VideoPlayer");
|
|
||||||
videoComponent = new VideoComponent();
|
|
||||||
playbin2.setVideoSink(videoComponent.getElement());
|
|
||||||
|
|
||||||
videoPanel.removeAll();
|
|
||||||
videoPanel.setLayout(new BoxLayout(videoPanel, BoxLayout.Y_AXIS));
|
|
||||||
videoPanel.add(videoComponent);
|
|
||||||
videoPanel.revalidate();
|
|
||||||
videoPanel.repaint();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void stopVideo() {
|
|
||||||
if(playbin2 != null && playbin2.isPlaying()) {
|
|
||||||
playbin2.stop();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isSupported(Node node) {
|
public boolean isSupported(Node node) {
|
||||||
stopVideo();
|
|
||||||
if (node == null) {
|
if (node == null) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -286,14 +336,13 @@ public class DataContentViewerMedia extends javax.swing.JPanel implements DataCo
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(file.getSize() == 0) {
|
if (file.getSize() == 0) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
String name = file.getName().toLowerCase();
|
String name = file.getName().toLowerCase();
|
||||||
|
|
||||||
if(containsExt(name, IMAGES) || containsExt(name, AUDIOS) || containsExt(name, VIDEOS)) {
|
if (containsExt(name, IMAGES) || containsExt(name, AUDIOS) || containsExt(name, VIDEOS)) {
|
||||||
resetVideo();
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -302,7 +351,7 @@ public class DataContentViewerMedia extends javax.swing.JPanel implements DataCo
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int isPreferred(Node node, boolean isSupported) {
|
public int isPreferred(Node node, boolean isSupported) {
|
||||||
if(isSupported) {
|
if (isSupported) {
|
||||||
return 7;
|
return 7;
|
||||||
} else {
|
} else {
|
||||||
return 0;
|
return 0;
|
||||||
@ -334,17 +383,21 @@ public class DataContentViewerMedia extends javax.swing.JPanel implements DataCo
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Thread that extracts and plays a file */
|
/* Thread that extracts and plays a file */
|
||||||
private class ExtractMedia extends SwingWorker<Object,Void> {
|
private class ExtractMedia extends SwingWorker<Object, Void> {
|
||||||
|
|
||||||
private ProgressHandle progress;
|
private ProgressHandle progress;
|
||||||
boolean success = false;
|
boolean success = false;
|
||||||
private File sFile;
|
private File sFile;
|
||||||
private java.io.File jFile;
|
private java.io.File jFile;
|
||||||
|
String duration;
|
||||||
|
String position;
|
||||||
|
|
||||||
ExtractMedia(org.sleuthkit.datamodel.File sFile, java.io.File jFile){
|
ExtractMedia(org.sleuthkit.datamodel.File sFile, java.io.File jFile) {
|
||||||
this.sFile = sFile;
|
this.sFile = sFile;
|
||||||
this.jFile = jFile;
|
this.jFile = jFile;
|
||||||
};
|
}
|
||||||
|
|
||||||
|
;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected Object doInBackground() throws Exception {
|
protected Object doInBackground() throws Exception {
|
||||||
@ -357,9 +410,9 @@ public class DataContentViewerMedia extends javax.swing.JPanel implements DataCo
|
|||||||
});
|
});
|
||||||
progressLabel.setText("Buffering...");
|
progressLabel.setText("Buffering...");
|
||||||
progress.start();
|
progress.start();
|
||||||
progress.switchToIndeterminate();
|
progress.switchToDeterminate(100);
|
||||||
try {
|
try {
|
||||||
ContentUtils.writeToFile(sFile, jFile);
|
ContentUtils.writeToFile(sFile, jFile, progress, this, true);
|
||||||
} catch (IOException ex) {
|
} catch (IOException ex) {
|
||||||
logger.log(Level.WARNING, "Error buffering file", ex);
|
logger.log(Level.WARNING, "Error buffering file", ex);
|
||||||
}
|
}
|
||||||
@ -370,45 +423,70 @@ public class DataContentViewerMedia extends javax.swing.JPanel implements DataCo
|
|||||||
/* clean up or start the worker threads */
|
/* clean up or start the worker threads */
|
||||||
@Override
|
@Override
|
||||||
protected void done() {
|
protected void done() {
|
||||||
|
try {
|
||||||
|
super.get(); //block and get all exceptions thrown while doInBackground()
|
||||||
|
} catch (CancellationException ex) {
|
||||||
|
logger.log(Level.INFO, "Media buffering was canceled.");
|
||||||
|
} catch (InterruptedException ex) {
|
||||||
|
logger.log(Level.INFO, "Media buffering was interrupted.");
|
||||||
|
} catch (Exception ex) {
|
||||||
|
logger.log(Level.SEVERE, "Fatal error during media buffering.", ex);
|
||||||
|
} finally {
|
||||||
progress.finish();
|
progress.finish();
|
||||||
if (success) {
|
if (!this.isCancelled()) {
|
||||||
play();
|
play();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private void play() {
|
private void play() {
|
||||||
if (jFile == null || !jFile.exists()) {
|
if (jFile == null || !jFile.exists()) {
|
||||||
progressLabel.setText("Error buffering file");
|
progressLabel.setText("Error buffering file");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
playbin2.setInputFile(jFile);
|
ClockTime dur = null;
|
||||||
|
synchronized (playbinLock) {
|
||||||
playbin2.play(); // must play, then pause and get state to get duration.
|
playbin2.play(); // must play, then pause and get state to get duration.
|
||||||
playbin2.pause();
|
playbin2.pause();
|
||||||
playbin2.getState();
|
playbin2.getState();
|
||||||
String duration = playbin2.queryDuration().toString();
|
dur = playbin2.queryDuration();
|
||||||
durationMillis = playbin2.queryDuration().toMillis();
|
}
|
||||||
progressSlider.setMaximum((int)durationMillis);
|
duration = dur.toString();
|
||||||
|
durationMillis = dur.toMillis();
|
||||||
|
|
||||||
|
progressSlider.setMaximum((int) durationMillis);
|
||||||
progressSlider.setMinimum(0);
|
progressSlider.setMinimum(0);
|
||||||
final String finalDuration;
|
final String finalDuration;
|
||||||
if(duration.length() == 8 && duration.substring(0,3).equals("00:")) {
|
if (duration.length() == 8 && duration.substring(0, 3).equals("00:")) {
|
||||||
finalDuration = duration.substring(3);
|
finalDuration = duration.substring(3);
|
||||||
progressLabel.setText("00:00/" + duration);
|
progressLabel.setText("00:00/" + duration);
|
||||||
} else {
|
} else {
|
||||||
finalDuration = duration;
|
finalDuration = duration;
|
||||||
progressLabel.setText("00:00:00/" + duration);
|
progressLabel.setText("00:00:00/" + duration);
|
||||||
}
|
}
|
||||||
|
synchronized (playbinLock) {
|
||||||
playbin2.play();
|
playbin2.play();
|
||||||
|
}
|
||||||
pauseButton.setText("||");
|
pauseButton.setText("||");
|
||||||
new Thread(new Runnable() {
|
new Thread(new Runnable() {
|
||||||
|
private boolean isPlayBinReady() {
|
||||||
|
synchronized (playbinLock) {
|
||||||
|
return playbin2 != null && !playbin2.getState().equals(State.NULL);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
long positionMillis = 0;
|
long positionMillis = 0;
|
||||||
while (positionMillis < durationMillis
|
while (positionMillis < durationMillis
|
||||||
&& playbin2 != null
|
&& isPlayBinReady() ) {
|
||||||
&& !playbin2.getState().equals(State.NULL)) {
|
ClockTime pos = null;
|
||||||
String position = playbin2.queryPosition().toString();
|
synchronized (playbinLock) {
|
||||||
positionMillis = playbin2.queryPosition().toMillis();
|
pos = playbin2.queryPosition();
|
||||||
|
}
|
||||||
|
position = pos.toString();
|
||||||
|
positionMillis = pos.toMillis();
|
||||||
|
|
||||||
if (position.length() == 8) {
|
if (position.length() == 8) {
|
||||||
position = position.substring(3);
|
position = position.substring(3);
|
||||||
}
|
}
|
||||||
@ -426,13 +504,22 @@ public class DataContentViewerMedia extends javax.swing.JPanel implements DataCo
|
|||||||
} else {
|
} else {
|
||||||
progressLabel.setText("00:00:00/" + finalDuration);
|
progressLabel.setText("00:00:00/" + finalDuration);
|
||||||
}
|
}
|
||||||
|
// If it reached the end
|
||||||
|
if (progressSlider.getValue() == progressSlider.getMaximum()) {
|
||||||
|
restartVideo();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void restartVideo() {
|
||||||
|
synchronized (playbinLock) {
|
||||||
if (playbin2 != null) {
|
if (playbin2 != null) {
|
||||||
playbin2.stop();
|
playbin2.stop();
|
||||||
playbin2.getState();
|
playbin2.setState(State.READY); // ready to be played again
|
||||||
|
}
|
||||||
|
}
|
||||||
pauseButton.setText("►");
|
pauseButton.setText("►");
|
||||||
progressSlider.setValue(0);
|
progressSlider.setValue(0);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}).start();
|
}).start();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -64,7 +64,7 @@ import org.sleuthkit.autopsy.datamodel.Views;
|
|||||||
import org.sleuthkit.autopsy.datamodel.ViewsNode;
|
import org.sleuthkit.autopsy.datamodel.ViewsNode;
|
||||||
import org.sleuthkit.autopsy.ingest.IngestManager;
|
import org.sleuthkit.autopsy.ingest.IngestManager;
|
||||||
import org.sleuthkit.autopsy.ingest.IngestManager.IngestModuleEvent;
|
import org.sleuthkit.autopsy.ingest.IngestManager.IngestModuleEvent;
|
||||||
import org.sleuthkit.autopsy.ingest.ServiceDataEvent;
|
import org.sleuthkit.autopsy.ingest.ModuleDataEvent;
|
||||||
import org.sleuthkit.datamodel.BlackboardArtifact;
|
import org.sleuthkit.datamodel.BlackboardArtifact;
|
||||||
import org.sleuthkit.datamodel.BlackboardAttribute;
|
import org.sleuthkit.datamodel.BlackboardAttribute;
|
||||||
import org.sleuthkit.datamodel.Content;
|
import org.sleuthkit.datamodel.Content;
|
||||||
@ -685,7 +685,7 @@ public final class DirectoryTreeTopComponent extends TopComponent implements Dat
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (changed.equals(IngestModuleEvent.DATA.toString())) {
|
if (changed.equals(IngestModuleEvent.DATA.toString())) {
|
||||||
final ServiceDataEvent event = (ServiceDataEvent) oldValue;
|
final ModuleDataEvent event = (ModuleDataEvent) oldValue;
|
||||||
SwingUtilities.invokeLater(new Runnable() {
|
SwingUtilities.invokeLater(new Runnable() {
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
|
@ -32,11 +32,12 @@ import java.util.Collection;
|
|||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
import java.util.logging.Level;
|
import java.util.logging.Level;
|
||||||
import java.util.logging.Logger;
|
import java.util.logging.Logger;
|
||||||
import org.sleuthkit.autopsy.ingest.IngestManagerProxy;
|
import org.sleuthkit.autopsy.ingest.IngestServices;
|
||||||
import org.sleuthkit.autopsy.ingest.IngestMessage;
|
import org.sleuthkit.autopsy.ingest.IngestMessage;
|
||||||
import org.sleuthkit.autopsy.ingest.IngestMessage.MessageType;
|
import org.sleuthkit.autopsy.ingest.IngestMessage.MessageType;
|
||||||
import org.sleuthkit.autopsy.ingest.IngestServiceAbstract;
|
import org.sleuthkit.autopsy.ingest.IngestModuleAbstract;
|
||||||
import org.sleuthkit.autopsy.ingest.IngestServiceAbstractFile;
|
import org.sleuthkit.autopsy.ingest.IngestModuleAbstractFile;
|
||||||
|
import org.sleuthkit.autopsy.ingest.IngestModuleInit;
|
||||||
import org.sleuthkit.datamodel.AbstractFile;
|
import org.sleuthkit.datamodel.AbstractFile;
|
||||||
import org.sleuthkit.datamodel.BlackboardArtifact;
|
import org.sleuthkit.datamodel.BlackboardArtifact;
|
||||||
import org.sleuthkit.datamodel.BlackboardAttribute;
|
import org.sleuthkit.datamodel.BlackboardAttribute;
|
||||||
@ -51,29 +52,31 @@ import org.sleuthkit.datamodel.TskData.TSK_DB_FILES_TYPE_ENUM;
|
|||||||
* Ingests an image file and, if available, adds it's date, latitude, longitude,
|
* Ingests an image file and, if available, adds it's date, latitude, longitude,
|
||||||
* altitude, device model, and device make to a blackboard artifact.
|
* altitude, device model, and device make to a blackboard artifact.
|
||||||
*/
|
*/
|
||||||
public final class ExifParserFileIngestService implements IngestServiceAbstractFile {
|
public final class ExifParserFileIngestModule implements IngestModuleAbstractFile {
|
||||||
|
|
||||||
|
private IngestServices services;
|
||||||
|
|
||||||
final String MODULE_NAME = "Exif Parser";
|
final String MODULE_NAME = "Exif Parser";
|
||||||
private static final Logger logger = Logger.getLogger(ExifParserFileIngestService.class.getName());
|
private static final Logger logger = Logger.getLogger(ExifParserFileIngestModule.class.getName());
|
||||||
private static ExifParserFileIngestService defaultInstance = null;
|
private static ExifParserFileIngestModule defaultInstance = null;
|
||||||
private IngestManagerProxy managerProxy;
|
|
||||||
private static int messageId = 0;
|
private static int messageId = 0;
|
||||||
|
|
||||||
//file ingest services require a private constructor
|
//file ingest modules require a private constructor
|
||||||
//to ensure singleton instances
|
//to ensure singleton instances
|
||||||
private ExifParserFileIngestService() {
|
private ExifParserFileIngestModule() {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//default instance used for service registration
|
//default instance used for module registration
|
||||||
public static synchronized ExifParserFileIngestService getDefault() {
|
public static synchronized ExifParserFileIngestModule getDefault() {
|
||||||
if (defaultInstance == null) {
|
if (defaultInstance == null) {
|
||||||
defaultInstance = new ExifParserFileIngestService();
|
defaultInstance = new ExifParserFileIngestModule();
|
||||||
}
|
}
|
||||||
return defaultInstance;
|
return defaultInstance;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public IngestServiceAbstractFile.ProcessResult process(AbstractFile content) {
|
public IngestModuleAbstractFile.ProcessResult process(AbstractFile content) {
|
||||||
if(content.getType().equals(TSK_DB_FILES_TYPE_ENUM.FS)) {
|
if(content.getType().equals(TSK_DB_FILES_TYPE_ENUM.FS)) {
|
||||||
FsContent fsContent = (FsContent) content;
|
FsContent fsContent = (FsContent) content;
|
||||||
if(fsContent.isFile()) {
|
if(fsContent.isFile()) {
|
||||||
@ -83,10 +86,10 @@ public final class ExifParserFileIngestService implements IngestServiceAbstractF
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return IngestServiceAbstractFile.ProcessResult.UNKNOWN;
|
return IngestModuleAbstractFile.ProcessResult.UNKNOWN;
|
||||||
}
|
}
|
||||||
|
|
||||||
public IngestServiceAbstractFile.ProcessResult processFile(FsContent f) {
|
public IngestModuleAbstractFile.ProcessResult processFile(FsContent f) {
|
||||||
InputStream in = null;
|
InputStream in = null;
|
||||||
BufferedInputStream bin = null;
|
BufferedInputStream bin = null;
|
||||||
|
|
||||||
@ -144,10 +147,10 @@ public final class ExifParserFileIngestService implements IngestServiceAbstractF
|
|||||||
bba.addAttributes(attributes);
|
bba.addAttributes(attributes);
|
||||||
}
|
}
|
||||||
|
|
||||||
return IngestServiceAbstractFile.ProcessResult.OK;
|
return IngestModuleAbstractFile.ProcessResult.OK;
|
||||||
|
|
||||||
} catch (TskCoreException ex) {
|
} catch (TskCoreException ex) {
|
||||||
Logger.getLogger(ExifParserFileIngestService.class.getName()).log(Level.SEVERE, null, ex);
|
Logger.getLogger(ExifParserFileIngestModule.class.getName()).log(Level.SEVERE, null, ex);
|
||||||
} catch (ImageProcessingException ex) {
|
} catch (ImageProcessingException ex) {
|
||||||
logger.log(Level.WARNING, "Failed to process the image.", ex);
|
logger.log(Level.WARNING, "Failed to process the image.", ex);
|
||||||
} catch (IOException ex) {
|
} catch (IOException ex) {
|
||||||
@ -162,7 +165,7 @@ public final class ExifParserFileIngestService implements IngestServiceAbstractF
|
|||||||
}
|
}
|
||||||
|
|
||||||
// If we got here, there was an error
|
// If we got here, there was an error
|
||||||
return IngestServiceAbstractFile.ProcessResult.ERROR;
|
return IngestModuleAbstractFile.ProcessResult.ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean parsableFormat(FsContent f) {
|
private boolean parsableFormat(FsContent f) {
|
||||||
@ -185,9 +188,9 @@ public final class ExifParserFileIngestService implements IngestServiceAbstractF
|
|||||||
logger.log(Level.INFO, "completed exif parsing " + this.toString());
|
logger.log(Level.INFO, "completed exif parsing " + this.toString());
|
||||||
|
|
||||||
final IngestMessage msg = IngestMessage.createMessage(++messageId, MessageType.INFO, this, "Complete");
|
final IngestMessage msg = IngestMessage.createMessage(++messageId, MessageType.INFO, this, "Complete");
|
||||||
managerProxy.postMessage(msg);
|
services.postMessage(msg);
|
||||||
|
|
||||||
//service specific cleanup due to completion here
|
//module specific cleanup due to completion here
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -201,23 +204,23 @@ public final class ExifParserFileIngestService implements IngestServiceAbstractF
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void init(IngestManagerProxy managerProxy) {
|
public void init(IngestModuleInit initContext) {
|
||||||
|
services = IngestServices.getDefault();
|
||||||
logger.log(Level.INFO, "init() " + this.toString());
|
logger.log(Level.INFO, "init() " + this.toString());
|
||||||
this.managerProxy = managerProxy;
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void stop() {
|
public void stop() {
|
||||||
logger.log(Level.INFO, "stop()");
|
logger.log(Level.INFO, "stop()");
|
||||||
managerProxy.postMessage(IngestMessage.createMessage(++messageId, MessageType.INFO, this, "Stopped"));
|
services.postMessage(IngestMessage.createMessage(++messageId, MessageType.INFO, this, "Stopped"));
|
||||||
|
|
||||||
//service specific cleanup due to interruption here
|
//module specific cleanup due to interruption here
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public IngestServiceAbstract.ServiceType getType() {
|
public IngestModuleAbstract.ModuleType getType() {
|
||||||
return IngestServiceAbstract.ServiceType.AbstractFile;
|
return IngestModuleAbstract.ModuleType.AbstractFile;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
@ -2,9 +2,9 @@
|
|||||||
<!DOCTYPE filesystem PUBLIC "-//NetBeans//DTD Filesystem 1.2//EN" "http://www.netbeans.org/dtds/filesystem-1_2.dtd">
|
<!DOCTYPE filesystem PUBLIC "-//NetBeans//DTD Filesystem 1.2//EN" "http://www.netbeans.org/dtds/filesystem-1_2.dtd">
|
||||||
<filesystem>
|
<filesystem>
|
||||||
<folder name="Services">
|
<folder name="Services">
|
||||||
<file name="org-sleuthkit-autopsy-exifparser-ExifParserFileIngestService.instance">
|
<file name="org-sleuthkit-autopsy-exifparser-ExifParserFileIngestModule.instance">
|
||||||
<attr name="instanceOf" stringvalue="org.sleuthkit.autopsy.ingest.IngestServiceAbstractFile"/>
|
<attr name="instanceOf" stringvalue="org.sleuthkit.autopsy.ingest.IngestModuleAbstractFile"/>
|
||||||
<attr name="instanceCreate" methodvalue="org.sleuthkit.autopsy.exifparser.ExifParserFileIngestService.getDefault"/>
|
<attr name="instanceCreate" methodvalue="org.sleuthkit.autopsy.exifparser.ExifParserFileIngestModule.getDefault"/>
|
||||||
<attr name="position" intvalue="110"/>
|
<attr name="position" intvalue="110"/>
|
||||||
</file>
|
</file>
|
||||||
</folder>
|
</folder>
|
||||||
|
@ -25,11 +25,11 @@ import java.util.Map;
|
|||||||
import java.util.logging.Level;
|
import java.util.logging.Level;
|
||||||
import java.util.logging.Logger;
|
import java.util.logging.Logger;
|
||||||
import org.sleuthkit.autopsy.casemodule.Case;
|
import org.sleuthkit.autopsy.casemodule.Case;
|
||||||
import org.sleuthkit.autopsy.ingest.IngestManager;
|
import org.sleuthkit.autopsy.ingest.IngestServices;
|
||||||
import org.sleuthkit.autopsy.ingest.IngestManagerProxy;
|
|
||||||
import org.sleuthkit.autopsy.ingest.IngestMessage;
|
import org.sleuthkit.autopsy.ingest.IngestMessage;
|
||||||
import org.sleuthkit.autopsy.ingest.IngestServiceAbstractFile;
|
import org.sleuthkit.autopsy.ingest.IngestModuleAbstractFile;
|
||||||
import org.sleuthkit.autopsy.ingest.ServiceDataEvent;
|
import org.sleuthkit.autopsy.ingest.IngestModuleInit;
|
||||||
|
import org.sleuthkit.autopsy.ingest.ModuleDataEvent;
|
||||||
import org.sleuthkit.datamodel.BlackboardArtifact;
|
import org.sleuthkit.datamodel.BlackboardArtifact;
|
||||||
import org.sleuthkit.datamodel.BlackboardArtifact.ARTIFACT_TYPE;
|
import org.sleuthkit.datamodel.BlackboardArtifact.ARTIFACT_TYPE;
|
||||||
import org.sleuthkit.datamodel.BlackboardAttribute;
|
import org.sleuthkit.datamodel.BlackboardAttribute;
|
||||||
@ -44,14 +44,14 @@ import org.sleuthkit.datamodel.SleuthkitCase;
|
|||||||
import org.sleuthkit.datamodel.TskData;
|
import org.sleuthkit.datamodel.TskData;
|
||||||
import org.sleuthkit.datamodel.TskException;
|
import org.sleuthkit.datamodel.TskException;
|
||||||
|
|
||||||
public class HashDbIngestService implements IngestServiceAbstractFile {
|
public class HashDbIngestModule implements IngestModuleAbstractFile {
|
||||||
|
|
||||||
private static HashDbIngestService instance = null;
|
private static HashDbIngestModule instance = null;
|
||||||
public final static String MODULE_NAME = "Hash Lookup";
|
public final static String MODULE_NAME = "Hash Lookup";
|
||||||
public final static String MODULE_DESCRIPTION = "Identifies known and notables files using supplied hash databases, such as a standard NSRL database.";
|
public final static String MODULE_DESCRIPTION = "Identifies known and notables files using supplied hash databases, such as a standard NSRL database.";
|
||||||
private static final Logger logger = Logger.getLogger(HashDbIngestService.class.getName());
|
private static final Logger logger = Logger.getLogger(HashDbIngestModule.class.getName());
|
||||||
private Processor processor = new Processor();
|
private Processor processor = new Processor();
|
||||||
private IngestManagerProxy managerProxy;
|
private IngestServices services;
|
||||||
private SleuthkitCase skCase;
|
private SleuthkitCase skCase;
|
||||||
private static int messageId = 0;
|
private static int messageId = 0;
|
||||||
private int count;
|
private int count;
|
||||||
@ -66,29 +66,24 @@ public class HashDbIngestService implements IngestServiceAbstractFile {
|
|||||||
private Map<Integer, HashDb> knownBadSets = new HashMap<Integer, HashDb>();
|
private Map<Integer, HashDb> knownBadSets = new HashMap<Integer, HashDb>();
|
||||||
|
|
||||||
|
|
||||||
private HashDbIngestService() {
|
private HashDbIngestModule() {
|
||||||
count = 0;
|
count = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static synchronized HashDbIngestService getDefault() {
|
public static synchronized HashDbIngestModule getDefault() {
|
||||||
if (instance == null) {
|
if (instance == null) {
|
||||||
instance = new HashDbIngestService();
|
instance = new HashDbIngestModule();
|
||||||
}
|
}
|
||||||
return instance;
|
return instance;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* notification from manager that brand new processing should be initiated.
|
|
||||||
* Service loads its configuration and performs initialization
|
|
||||||
*
|
|
||||||
* @param managerProxy handle to the manager to postMessage() to
|
|
||||||
*/
|
|
||||||
@Override
|
@Override
|
||||||
public void init(IngestManagerProxy managerProxy) {
|
public void init(IngestModuleInit initContext) {
|
||||||
|
services = IngestServices.getDefault();
|
||||||
HashDbManagementPanel.getDefault().setIngestRunning(true);
|
HashDbManagementPanel.getDefault().setIngestRunning(true);
|
||||||
HashDbSimplePanel.setIngestRunning(true);
|
HashDbSimplePanel.setIngestRunning(true);
|
||||||
this.managerProxy = managerProxy;
|
this.services.postMessage(IngestMessage.createMessage(++messageId, IngestMessage.MessageType.INFO, this, "Started"));
|
||||||
this.managerProxy.postMessage(IngestMessage.createMessage(++messageId, IngestMessage.MessageType.INFO, this, "Started"));
|
|
||||||
this.skCase = Case.getCurrentCase().getSleuthkitCase();
|
this.skCase = Case.getCurrentCase().getSleuthkitCase();
|
||||||
try {
|
try {
|
||||||
HashDbXML hdbxml = HashDbXML.getCurrent();
|
HashDbXML hdbxml = HashDbXML.getCurrent();
|
||||||
@ -116,10 +111,10 @@ public class HashDbIngestService implements IngestServiceAbstractFile {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!nsrlIsSet) {
|
if (!nsrlIsSet) {
|
||||||
this.managerProxy.postMessage(IngestMessage.createWarningMessage(++messageId, this, "No NSRL database set", "Known file search will not be executed."));
|
this.services.postMessage(IngestMessage.createWarningMessage(++messageId, this, "No NSRL database set", "Known file search will not be executed."));
|
||||||
}
|
}
|
||||||
if (!knownBadIsSet) {
|
if (!knownBadIsSet) {
|
||||||
this.managerProxy.postMessage(IngestMessage.createWarningMessage(++messageId, this, "No known bad database set", "Known bad file search will not be executed."));
|
this.services.postMessage(IngestMessage.createWarningMessage(++messageId, this, "No known bad database set", "Known bad file search will not be executed."));
|
||||||
}
|
}
|
||||||
|
|
||||||
} catch (TskException ex) {
|
} catch (TskException ex) {
|
||||||
@ -127,10 +122,7 @@ public class HashDbIngestService implements IngestServiceAbstractFile {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* notification from manager that there is no more content to process and all work is done.
|
|
||||||
* Service performs any clean-up, notifies viewers and may also write results to the black-board
|
|
||||||
*/
|
|
||||||
@Override
|
@Override
|
||||||
public void complete() {
|
public void complete() {
|
||||||
StringBuilder detailsSb = new StringBuilder();
|
StringBuilder detailsSb = new StringBuilder();
|
||||||
@ -156,7 +148,7 @@ public class HashDbIngestService implements IngestServiceAbstractFile {
|
|||||||
}
|
}
|
||||||
|
|
||||||
detailsSb.append("</table>");
|
detailsSb.append("</table>");
|
||||||
managerProxy.postMessage(IngestMessage.createMessage(++messageId, IngestMessage.MessageType.INFO, this, "Hash Ingest Complete", detailsSb.toString()));
|
services.postMessage(IngestMessage.createMessage(++messageId, IngestMessage.MessageType.INFO, this, "Hash Ingest Complete", detailsSb.toString()));
|
||||||
|
|
||||||
HashDbManagementPanel.getDefault().setIngestRunning(false);
|
HashDbManagementPanel.getDefault().setIngestRunning(false);
|
||||||
HashDbSimplePanel.setIngestRunning(false);
|
HashDbSimplePanel.setIngestRunning(false);
|
||||||
@ -173,9 +165,9 @@ public class HashDbIngestService implements IngestServiceAbstractFile {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* get specific name of the service
|
* get specific name of the module
|
||||||
* should be unique across services, a user-friendly name of the service shown in GUI
|
* should be unique across modules, a user-friendly name of the module shown in GUI
|
||||||
* @return The name of this Ingest Service
|
* @return The name of this Ingest Module
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public String getName() {
|
public String getName() {
|
||||||
@ -199,8 +191,8 @@ public class HashDbIngestService implements IngestServiceAbstractFile {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ServiceType getType() {
|
public ModuleType getType() {
|
||||||
return ServiceType.AbstractFile;
|
return ModuleType.AbstractFile;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -266,13 +258,13 @@ public class HashDbIngestService implements IngestServiceAbstractFile {
|
|||||||
|
|
||||||
detailsSb.append("</table>");
|
detailsSb.append("</table>");
|
||||||
|
|
||||||
managerProxy.postMessage(IngestMessage.createDataMessage(++messageId, this,
|
services.postMessage(IngestMessage.createDataMessage(++messageId, this,
|
||||||
"Notable: " + abstractFile.getName(),
|
"Notable: " + abstractFile.getName(),
|
||||||
detailsSb.toString(),
|
detailsSb.toString(),
|
||||||
abstractFile.getName() + md5Hash,
|
abstractFile.getName() + md5Hash,
|
||||||
badFile));
|
badFile));
|
||||||
}
|
}
|
||||||
IngestManagerProxy.fireServiceDataEvent(new ServiceDataEvent(MODULE_NAME, ARTIFACT_TYPE.TSK_HASHSET_HIT, Collections.singletonList(badFile)));
|
services.fireModuleDataEvent(new ModuleDataEvent(MODULE_NAME, ARTIFACT_TYPE.TSK_HASHSET_HIT, Collections.singletonList(badFile)));
|
||||||
} catch (TskException ex) {
|
} catch (TskException ex) {
|
||||||
logger.log(Level.WARNING, "Error creating blackboard artifact", ex);
|
logger.log(Level.WARNING, "Error creating blackboard artifact", ex);
|
||||||
}
|
}
|
||||||
@ -293,11 +285,10 @@ public class HashDbIngestService implements IngestServiceAbstractFile {
|
|||||||
|
|
||||||
private ProcessResult process(FsContent fsContent) {
|
private ProcessResult process(FsContent fsContent) {
|
||||||
|
|
||||||
ProcessResult ret = ProcessResult.UNKNOWN;
|
ProcessResult ret = ProcessResult.OK;
|
||||||
boolean processFile = true;
|
boolean processFile = true;
|
||||||
if (fsContent.getSize() == 0
|
if (fsContent.getSize() == 0
|
||||||
|| fsContent.getKnown().equals(TskData.FileKnown.BAD)) {
|
|| fsContent.getKnown().equals(TskData.FileKnown.BAD)) {
|
||||||
ret = ProcessResult.OK;
|
|
||||||
processFile = false;
|
processFile = false;
|
||||||
}
|
}
|
||||||
if (processFile && (nsrlIsSet || knownBadIsSet)) {
|
if (processFile && (nsrlIsSet || knownBadIsSet)) {
|
||||||
@ -322,7 +313,6 @@ public class HashDbIngestService implements IngestServiceAbstractFile {
|
|||||||
String hashSetName = entry.getValue().getName();
|
String hashSetName = entry.getValue().getName();
|
||||||
processBadFile(fsContent, md5Hash, hashSetName, entry.getValue().getShowInboxMessages());
|
processBadFile(fsContent, md5Hash, hashSetName, entry.getValue().getShowInboxMessages());
|
||||||
}
|
}
|
||||||
ret = ProcessResult.OK;
|
|
||||||
}
|
}
|
||||||
if (!foundBad && nsrlIsSet) {
|
if (!foundBad && nsrlIsSet) {
|
||||||
long lookupstart = System.currentTimeMillis();
|
long lookupstart = System.currentTimeMillis();
|
||||||
@ -330,17 +320,16 @@ public class HashDbIngestService implements IngestServiceAbstractFile {
|
|||||||
lookuptime += (System.currentTimeMillis()-lookupstart);
|
lookuptime += (System.currentTimeMillis()-lookupstart);
|
||||||
if (status.equals(TskData.FileKnown.KNOWN)) {
|
if (status.equals(TskData.FileKnown.KNOWN)) {
|
||||||
skCase.setKnown(fsContent, status);
|
skCase.setKnown(fsContent, status);
|
||||||
ret = ProcessResult.COND_STOP;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (TskException ex) {
|
} catch (TskException ex) {
|
||||||
logger.log(Level.WARNING, "Couldn't analyze file " + name + " - see sleuthkit log for details", ex);
|
logger.log(Level.WARNING, "Couldn't analyze file " + name + " - see sleuthkit log for details", ex);
|
||||||
managerProxy.postMessage(IngestMessage.createErrorMessage(++messageId, HashDbIngestService.this, "Hash Lookup Error: " + name,
|
services.postMessage(IngestMessage.createErrorMessage(++messageId, HashDbIngestModule.this, "Hash Lookup Error: " + name,
|
||||||
"Error encountered while updating the hash values for " + name + "."));
|
"Error encountered while updating the hash values for " + name + "."));
|
||||||
ret = ProcessResult.ERROR;
|
ret = ProcessResult.ERROR;
|
||||||
} catch (IOException ex) {
|
} catch (IOException ex) {
|
||||||
logger.log(Level.WARNING, "Error reading file " + name, ex);
|
logger.log(Level.WARNING, "Error reading file " + name, ex);
|
||||||
managerProxy.postMessage(IngestMessage.createErrorMessage(++messageId, HashDbIngestService.this, "Read Error: " + name,
|
services.postMessage(IngestMessage.createErrorMessage(++messageId, HashDbIngestModule.this, "Read Error: " + name,
|
||||||
"Error encountered while calculating the hash value for " + name + "."));
|
"Error encountered while calculating the hash value for " + name + "."));
|
||||||
ret = ProcessResult.ERROR;
|
ret = ProcessResult.ERROR;
|
||||||
}
|
}
|
||||||
@ -357,7 +346,7 @@ public class HashDbIngestService implements IngestServiceAbstractFile {
|
|||||||
}
|
}
|
||||||
catch (IOException ex) {
|
catch (IOException ex) {
|
||||||
logger.log(Level.WARNING, "Error reading file " + name, ex);
|
logger.log(Level.WARNING, "Error reading file " + name, ex);
|
||||||
managerProxy.postMessage(IngestMessage.createErrorMessage(++messageId, HashDbIngestService.this, "Read Error: " + name,
|
services.postMessage(IngestMessage.createErrorMessage(++messageId, HashDbIngestModule.this, "Read Error: " + name,
|
||||||
"Error encountered while calculating the hash value for " + name + " without databases."));
|
"Error encountered while calculating the hash value for " + name + " without databases."));
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -40,9 +40,9 @@
|
|||||||
</folder>
|
</folder>
|
||||||
</folder>
|
</folder>
|
||||||
<folder name="Services">
|
<folder name="Services">
|
||||||
<file name="org-sleuthkit-autopsy-hashdatabase-HashDbIngestService.instance">
|
<file name="org-sleuthkit-autopsy-hashdatabase-HashDbIngestModule.instance">
|
||||||
<attr name="instanceOf" stringvalue="org.sleuthkit.autopsy.ingest.IngestServiceAbstractFile"/>
|
<attr name="instanceOf" stringvalue="org.sleuthkit.autopsy.ingest.IngestModuleAbstractFile"/>
|
||||||
<attr name="instanceCreate" methodvalue="org.sleuthkit.autopsy.hashdatabase.HashDbIngestService.getDefault"/>
|
<attr name="instanceCreate" methodvalue="org.sleuthkit.autopsy.hashdatabase.HashDbIngestModule.getDefault"/>
|
||||||
<attr name="position" intvalue="200"/>
|
<attr name="position" intvalue="200"/>
|
||||||
</file>
|
</file>
|
||||||
</folder>
|
</folder>
|
||||||
|
@ -7,14 +7,14 @@ HINT_IngestTopComponent=Ingest window
|
|||||||
OpenIDE-Module-Name=Ingest
|
OpenIDE-Module-Name=Ingest
|
||||||
IngestTopComponent.messageFrame.title=Messages
|
IngestTopComponent.messageFrame.title=Messages
|
||||||
IngestTopComponent.ingestProgressLabel.text=File Ingest Progress
|
IngestTopComponent.ingestProgressLabel.text=File Ingest Progress
|
||||||
IngestControlPanel.topLable.text=Image ingest services
|
IngestControlPanel.topLable.text=Image ingest modules
|
||||||
IngestControlPanel.startButton.text=Start
|
IngestControlPanel.startButton.text=Start
|
||||||
IngestDialogPanel.ingestServicesLabel.text=Image Ingest Services
|
IngestDialogPanel.ingestServicesLabel.text=Image Ingest Modules
|
||||||
IngestDialogForm2.okButton.text=OK
|
IngestDialogForm2.okButton.text=OK
|
||||||
IngestDialogForm2.cancelButton.text=Cancel
|
IngestDialogForm2.cancelButton.text=Cancel
|
||||||
IngestDialogForm.cancelButton.text=Cancel
|
IngestDialogForm.cancelButton.text=Cancel
|
||||||
IngestDialogForm.startButton.text=Start
|
IngestDialogForm.startButton.text=Start
|
||||||
IngestDialogForm.jLabel1.text=Ingest Services
|
IngestDialogForm.jLabel1.text=Ingest Modules
|
||||||
IngestTopComponent.refreshFreqLabel.text=Refresh frequency
|
IngestTopComponent.refreshFreqLabel.text=Refresh frequency
|
||||||
IngestMessageDetailsPanel.backButton.text=
|
IngestMessageDetailsPanel.backButton.text=
|
||||||
IngestMessageDetailsPanel.viewArtifactButton.text=Go to Result
|
IngestMessageDetailsPanel.viewArtifactButton.text=Go to Result
|
||||||
|
@ -28,7 +28,7 @@
|
|||||||
<Group type="102" alignment="0" attributes="0">
|
<Group type="102" alignment="0" attributes="0">
|
||||||
<EmptySpace max="-2" attributes="0"/>
|
<EmptySpace max="-2" attributes="0"/>
|
||||||
<Group type="103" groupAlignment="0" attributes="0">
|
<Group type="103" groupAlignment="0" attributes="0">
|
||||||
<Component id="servicesScrollPane" max="32767" attributes="1"/>
|
<Component id="modulesScrollPane" max="32767" attributes="1"/>
|
||||||
<Component id="timePanel" alignment="0" max="32767" attributes="1"/>
|
<Component id="timePanel" alignment="0" max="32767" attributes="1"/>
|
||||||
<Component id="processUnallocPanel" alignment="0" max="32767" attributes="0"/>
|
<Component id="processUnallocPanel" alignment="0" max="32767" attributes="0"/>
|
||||||
</Group>
|
</Group>
|
||||||
@ -45,7 +45,7 @@
|
|||||||
<Group type="103" groupAlignment="0" attributes="0">
|
<Group type="103" groupAlignment="0" attributes="0">
|
||||||
<Component id="jPanel1" pref="235" max="32767" attributes="0"/>
|
<Component id="jPanel1" pref="235" max="32767" attributes="0"/>
|
||||||
<Group type="102" attributes="0">
|
<Group type="102" attributes="0">
|
||||||
<Component id="servicesScrollPane" pref="0" max="32767" attributes="0"/>
|
<Component id="modulesScrollPane" pref="0" max="32767" attributes="0"/>
|
||||||
<EmptySpace max="-2" attributes="0"/>
|
<EmptySpace max="-2" attributes="0"/>
|
||||||
<Component id="processUnallocPanel" min="-2" max="-2" attributes="0"/>
|
<Component id="processUnallocPanel" min="-2" max="-2" attributes="0"/>
|
||||||
<EmptySpace max="-2" attributes="0"/>
|
<EmptySpace max="-2" attributes="0"/>
|
||||||
@ -58,7 +58,7 @@
|
|||||||
</DimensionLayout>
|
</DimensionLayout>
|
||||||
</Layout>
|
</Layout>
|
||||||
<SubComponents>
|
<SubComponents>
|
||||||
<Container class="javax.swing.JScrollPane" name="servicesScrollPane">
|
<Container class="javax.swing.JScrollPane" name="modulesScrollPane">
|
||||||
<Properties>
|
<Properties>
|
||||||
<Property name="border" type="javax.swing.border.Border" editor="org.netbeans.modules.form.editors2.BorderEditor">
|
<Property name="border" type="javax.swing.border.Border" editor="org.netbeans.modules.form.editors2.BorderEditor">
|
||||||
<Border info="org.netbeans.modules.form.compat2.border.LineBorderInfo">
|
<Border info="org.netbeans.modules.form.compat2.border.LineBorderInfo">
|
||||||
@ -74,7 +74,7 @@
|
|||||||
|
|
||||||
<Layout class="org.netbeans.modules.form.compat2.layouts.support.JScrollPaneSupportLayout"/>
|
<Layout class="org.netbeans.modules.form.compat2.layouts.support.JScrollPaneSupportLayout"/>
|
||||||
<SubComponents>
|
<SubComponents>
|
||||||
<Component class="javax.swing.JTable" name="servicesTable">
|
<Component class="javax.swing.JTable" name="modulesTable">
|
||||||
<Properties>
|
<Properties>
|
||||||
<Property name="background" type="java.awt.Color" editor="org.netbeans.beaninfo.editors.ColorEditor">
|
<Property name="background" type="java.awt.Color" editor="org.netbeans.beaninfo.editors.ColorEditor">
|
||||||
<Color blue="f0" green="f0" red="f0" type="rgb"/>
|
<Color blue="f0" green="f0" red="f0" type="rgb"/>
|
||||||
@ -180,18 +180,11 @@
|
|||||||
<Group type="102" attributes="0">
|
<Group type="102" attributes="0">
|
||||||
<EmptySpace max="-2" attributes="0"/>
|
<EmptySpace max="-2" attributes="0"/>
|
||||||
<Group type="103" groupAlignment="0" attributes="0">
|
<Group type="103" groupAlignment="0" attributes="0">
|
||||||
<Group type="102" alignment="0" attributes="0">
|
<Component id="timeRadioButton1" alignment="0" min="-2" max="-2" attributes="0"/>
|
||||||
<EmptySpace min="-2" pref="0" max="-2" attributes="0"/>
|
|
||||||
<Component id="timeRadioButton1" min="-2" max="-2" attributes="0"/>
|
|
||||||
</Group>
|
|
||||||
<Group type="102" attributes="0">
|
|
||||||
<Group type="103" groupAlignment="0" attributes="0">
|
|
||||||
<Component id="timeLabel" min="-2" max="-2" attributes="0"/>
|
<Component id="timeLabel" min="-2" max="-2" attributes="0"/>
|
||||||
<Component id="timeRadioButton2" alignment="0" min="-2" max="-2" attributes="0"/>
|
<Component id="timeRadioButton2" alignment="0" min="-2" max="-2" attributes="0"/>
|
||||||
<Component id="timeRadioButton3" alignment="0" min="-2" max="-2" attributes="0"/>
|
<Component id="timeRadioButton3" alignment="0" min="-2" max="-2" attributes="0"/>
|
||||||
</Group>
|
</Group>
|
||||||
</Group>
|
|
||||||
</Group>
|
|
||||||
<EmptySpace max="32767" attributes="0"/>
|
<EmptySpace max="32767" attributes="0"/>
|
||||||
</Group>
|
</Group>
|
||||||
</Group>
|
</Group>
|
||||||
|
@ -44,15 +44,15 @@ import org.sleuthkit.autopsy.ingest.IngestManager.UpdateFrequency;
|
|||||||
import org.sleuthkit.datamodel.Image;
|
import org.sleuthkit.datamodel.Image;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* main configuration panel for all ingest services, reusable JPanel component
|
* main configuration panel for all ingest modules, reusable JPanel component
|
||||||
*/
|
*/
|
||||||
public class IngestDialogPanel extends javax.swing.JPanel implements IngestConfigurator {
|
public class IngestDialogPanel extends javax.swing.JPanel implements IngestConfigurator {
|
||||||
|
|
||||||
private IngestManager manager = null;
|
private IngestManager manager = null;
|
||||||
private List<IngestServiceAbstract> services;
|
private List<IngestModuleAbstract> modules;
|
||||||
private IngestServiceAbstract currentService;
|
private IngestModuleAbstract currentModule;
|
||||||
private Map<String, Boolean> serviceStates;
|
private Map<String, Boolean> moduleStates;
|
||||||
private ServicesTableModel tableModel;
|
private ModulesTableModel tableModel;
|
||||||
private static final Logger logger = Logger.getLogger(IngestDialogPanel.class.getName());
|
private static final Logger logger = Logger.getLogger(IngestDialogPanel.class.getName());
|
||||||
// The image that's just been added to the database
|
// The image that's just been added to the database
|
||||||
private Image image;
|
private Image image;
|
||||||
@ -60,9 +60,9 @@ public class IngestDialogPanel extends javax.swing.JPanel implements IngestConfi
|
|||||||
|
|
||||||
/** Creates new form IngestDialogPanel */
|
/** Creates new form IngestDialogPanel */
|
||||||
private IngestDialogPanel() {
|
private IngestDialogPanel() {
|
||||||
tableModel = new ServicesTableModel();
|
tableModel = new ModulesTableModel();
|
||||||
services = new ArrayList<IngestServiceAbstract>();
|
modules = new ArrayList<IngestModuleAbstract>();
|
||||||
serviceStates = new HashMap<String, Boolean>();
|
moduleStates = new HashMap<String, Boolean>();
|
||||||
initComponents();
|
initComponents();
|
||||||
customizeComponents();
|
customizeComponents();
|
||||||
}
|
}
|
||||||
@ -75,15 +75,15 @@ public class IngestDialogPanel extends javax.swing.JPanel implements IngestConfi
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void customizeComponents() {
|
private void customizeComponents() {
|
||||||
servicesTable.setModel(tableModel);
|
modulesTable.setModel(tableModel);
|
||||||
this.manager = IngestManager.getDefault();
|
this.manager = IngestManager.getDefault();
|
||||||
Collection<IngestServiceImage> imageServices = IngestManager.enumerateImageServices();
|
Collection<IngestModuleImage> imageModules = IngestManager.enumerateImageModules();
|
||||||
for (final IngestServiceImage service : imageServices) {
|
for (final IngestModuleImage module : imageModules) {
|
||||||
addService(service);
|
addModule(module);
|
||||||
}
|
}
|
||||||
Collection<IngestServiceAbstractFile> fsServices = IngestManager.enumerateAbstractFileServices();
|
Collection<IngestModuleAbstractFile> fsModules = IngestManager.enumerateAbstractFileModules();
|
||||||
for (final IngestServiceAbstractFile service : fsServices) {
|
for (final IngestModuleAbstractFile module : fsModules) {
|
||||||
addService(service);
|
addModule(module);
|
||||||
}
|
}
|
||||||
|
|
||||||
//time setting
|
//time setting
|
||||||
@ -113,17 +113,17 @@ public class IngestDialogPanel extends javax.swing.JPanel implements IngestConfi
|
|||||||
//
|
//
|
||||||
}
|
}
|
||||||
|
|
||||||
servicesTable.setTableHeader(null);
|
modulesTable.setTableHeader(null);
|
||||||
servicesTable.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
|
modulesTable.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
|
||||||
|
|
||||||
//custom renderer for tooltips
|
//custom renderer for tooltips
|
||||||
|
|
||||||
ServiceTableRenderer renderer = new ServiceTableRenderer();
|
ModulesTableRenderer renderer = new ModulesTableRenderer();
|
||||||
//customize column witdhs
|
//customize column witdhs
|
||||||
final int width = servicesScrollPane.getPreferredSize().width;
|
final int width = modulesScrollPane.getPreferredSize().width;
|
||||||
TableColumn column = null;
|
TableColumn column = null;
|
||||||
for (int i = 0; i < servicesTable.getColumnCount(); i++) {
|
for (int i = 0; i < modulesTable.getColumnCount(); i++) {
|
||||||
column = servicesTable.getColumnModel().getColumn(i);
|
column = modulesTable.getColumnModel().getColumn(i);
|
||||||
if (i == 0) {
|
if (i == 0) {
|
||||||
column.setPreferredWidth(((int) (width * 0.15)));
|
column.setPreferredWidth(((int) (width * 0.15)));
|
||||||
} else {
|
} else {
|
||||||
@ -132,7 +132,7 @@ public class IngestDialogPanel extends javax.swing.JPanel implements IngestConfi
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
servicesTable.getSelectionModel().addListSelectionListener(new ListSelectionListener() {
|
modulesTable.getSelectionModel().addListSelectionListener(new ListSelectionListener() {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void valueChanged(ListSelectionEvent e) {
|
public void valueChanged(ListSelectionEvent e) {
|
||||||
@ -140,11 +140,11 @@ public class IngestDialogPanel extends javax.swing.JPanel implements IngestConfi
|
|||||||
if (!listSelectionModel.isSelectionEmpty()) {
|
if (!listSelectionModel.isSelectionEmpty()) {
|
||||||
save();
|
save();
|
||||||
int index = listSelectionModel.getMinSelectionIndex();
|
int index = listSelectionModel.getMinSelectionIndex();
|
||||||
currentService = services.get(index);
|
currentModule = modules.get(index);
|
||||||
reloadSimpleConfiguration();
|
reloadSimpleConfiguration();
|
||||||
advancedButton.setEnabled(currentService.hasAdvancedConfiguration());
|
advancedButton.setEnabled(currentModule.hasAdvancedConfiguration());
|
||||||
} else {
|
} else {
|
||||||
currentService = null;
|
currentModule = null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@ -176,10 +176,10 @@ public class IngestDialogPanel extends javax.swing.JPanel implements IngestConfi
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void addService(IngestServiceAbstract service) {
|
private void addModule(IngestModuleAbstract module) {
|
||||||
final String serviceName = service.getName();
|
final String moduleName = module.getName();
|
||||||
services.add(service);
|
modules.add(module);
|
||||||
serviceStates.put(serviceName, true);
|
moduleStates.put(moduleName, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** This method is called from within the constructor to
|
/** This method is called from within the constructor to
|
||||||
@ -192,8 +192,8 @@ public class IngestDialogPanel extends javax.swing.JPanel implements IngestConfi
|
|||||||
private void initComponents() {
|
private void initComponents() {
|
||||||
|
|
||||||
timeGroup = new javax.swing.ButtonGroup();
|
timeGroup = new javax.swing.ButtonGroup();
|
||||||
servicesScrollPane = new javax.swing.JScrollPane();
|
modulesScrollPane = new javax.swing.JScrollPane();
|
||||||
servicesTable = new javax.swing.JTable();
|
modulesTable = new javax.swing.JTable();
|
||||||
jPanel1 = new javax.swing.JPanel();
|
jPanel1 = new javax.swing.JPanel();
|
||||||
advancedButton = new javax.swing.JButton();
|
advancedButton = new javax.swing.JButton();
|
||||||
jSeparator2 = new javax.swing.JSeparator();
|
jSeparator2 = new javax.swing.JSeparator();
|
||||||
@ -209,11 +209,11 @@ public class IngestDialogPanel extends javax.swing.JPanel implements IngestConfi
|
|||||||
|
|
||||||
setPreferredSize(new java.awt.Dimension(522, 257));
|
setPreferredSize(new java.awt.Dimension(522, 257));
|
||||||
|
|
||||||
servicesScrollPane.setBorder(javax.swing.BorderFactory.createLineBorder(new java.awt.Color(160, 160, 160)));
|
modulesScrollPane.setBorder(javax.swing.BorderFactory.createLineBorder(new java.awt.Color(160, 160, 160)));
|
||||||
servicesScrollPane.setPreferredSize(new java.awt.Dimension(160, 160));
|
modulesScrollPane.setPreferredSize(new java.awt.Dimension(160, 160));
|
||||||
|
|
||||||
servicesTable.setBackground(new java.awt.Color(240, 240, 240));
|
modulesTable.setBackground(new java.awt.Color(240, 240, 240));
|
||||||
servicesTable.setModel(new javax.swing.table.DefaultTableModel(
|
modulesTable.setModel(new javax.swing.table.DefaultTableModel(
|
||||||
new Object [][] {
|
new Object [][] {
|
||||||
|
|
||||||
},
|
},
|
||||||
@ -221,9 +221,9 @@ public class IngestDialogPanel extends javax.swing.JPanel implements IngestConfi
|
|||||||
|
|
||||||
}
|
}
|
||||||
));
|
));
|
||||||
servicesTable.setShowHorizontalLines(false);
|
modulesTable.setShowHorizontalLines(false);
|
||||||
servicesTable.setShowVerticalLines(false);
|
modulesTable.setShowVerticalLines(false);
|
||||||
servicesScrollPane.setViewportView(servicesTable);
|
modulesScrollPane.setViewportView(modulesTable);
|
||||||
|
|
||||||
jPanel1.setBorder(javax.swing.BorderFactory.createLineBorder(new java.awt.Color(160, 160, 160)));
|
jPanel1.setBorder(javax.swing.BorderFactory.createLineBorder(new java.awt.Color(160, 160, 160)));
|
||||||
jPanel1.setPreferredSize(new java.awt.Dimension(338, 257));
|
jPanel1.setPreferredSize(new java.awt.Dimension(338, 257));
|
||||||
@ -290,14 +290,10 @@ public class IngestDialogPanel extends javax.swing.JPanel implements IngestConfi
|
|||||||
.addGroup(timePanelLayout.createSequentialGroup()
|
.addGroup(timePanelLayout.createSequentialGroup()
|
||||||
.addContainerGap()
|
.addContainerGap()
|
||||||
.addGroup(timePanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
.addGroup(timePanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||||
.addGroup(timePanelLayout.createSequentialGroup()
|
.addComponent(timeRadioButton1)
|
||||||
.addGap(0, 0, 0)
|
|
||||||
.addComponent(timeRadioButton1))
|
|
||||||
.addGroup(timePanelLayout.createSequentialGroup()
|
|
||||||
.addGroup(timePanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
|
||||||
.addComponent(timeLabel)
|
.addComponent(timeLabel)
|
||||||
.addComponent(timeRadioButton2)
|
.addComponent(timeRadioButton2)
|
||||||
.addComponent(timeRadioButton3))))
|
.addComponent(timeRadioButton3))
|
||||||
.addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
|
.addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
|
||||||
);
|
);
|
||||||
timePanelLayout.setVerticalGroup(
|
timePanelLayout.setVerticalGroup(
|
||||||
@ -347,7 +343,7 @@ public class IngestDialogPanel extends javax.swing.JPanel implements IngestConfi
|
|||||||
.addGroup(layout.createSequentialGroup()
|
.addGroup(layout.createSequentialGroup()
|
||||||
.addContainerGap()
|
.addContainerGap()
|
||||||
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||||
.addComponent(servicesScrollPane, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
|
.addComponent(modulesScrollPane, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
|
||||||
.addComponent(timePanel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
|
.addComponent(timePanel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
|
||||||
.addComponent(processUnallocPanel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
|
.addComponent(processUnallocPanel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
|
||||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||||
@ -361,7 +357,7 @@ public class IngestDialogPanel extends javax.swing.JPanel implements IngestConfi
|
|||||||
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||||
.addComponent(jPanel1, javax.swing.GroupLayout.DEFAULT_SIZE, 235, Short.MAX_VALUE)
|
.addComponent(jPanel1, javax.swing.GroupLayout.DEFAULT_SIZE, 235, Short.MAX_VALUE)
|
||||||
.addGroup(layout.createSequentialGroup()
|
.addGroup(layout.createSequentialGroup()
|
||||||
.addComponent(servicesScrollPane, javax.swing.GroupLayout.PREFERRED_SIZE, 0, Short.MAX_VALUE)
|
.addComponent(modulesScrollPane, javax.swing.GroupLayout.PREFERRED_SIZE, 0, Short.MAX_VALUE)
|
||||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||||
.addComponent(processUnallocPanel, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
|
.addComponent(processUnallocPanel, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
|
||||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||||
@ -377,11 +373,11 @@ public class IngestDialogPanel extends javax.swing.JPanel implements IngestConfi
|
|||||||
@Override
|
@Override
|
||||||
public void actionPerformed(ActionEvent e) {
|
public void actionPerformed(ActionEvent e) {
|
||||||
dialog.close();
|
dialog.close();
|
||||||
currentService.saveAdvancedConfiguration();
|
currentModule.saveAdvancedConfiguration();
|
||||||
reloadSimpleConfiguration();
|
reloadSimpleConfiguration();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
dialog.display(currentService.getAdvancedConfiguration());
|
dialog.display(currentModule.getAdvancedConfiguration());
|
||||||
}//GEN-LAST:event_advancedButtonActionPerformed
|
}//GEN-LAST:event_advancedButtonActionPerformed
|
||||||
|
|
||||||
private void timeRadioButton1ActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_timeRadioButton1ActionPerformed
|
private void timeRadioButton1ActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_timeRadioButton1ActionPerformed
|
||||||
@ -397,10 +393,10 @@ private void timeRadioButton1ActionPerformed(java.awt.event.ActionEvent evt) {//
|
|||||||
private javax.swing.JPanel jPanel1;
|
private javax.swing.JPanel jPanel1;
|
||||||
private javax.swing.JScrollPane jScrollPane1;
|
private javax.swing.JScrollPane jScrollPane1;
|
||||||
private javax.swing.JSeparator jSeparator2;
|
private javax.swing.JSeparator jSeparator2;
|
||||||
|
private javax.swing.JScrollPane modulesScrollPane;
|
||||||
|
private javax.swing.JTable modulesTable;
|
||||||
private javax.swing.JCheckBox processUnallocCheckbox;
|
private javax.swing.JCheckBox processUnallocCheckbox;
|
||||||
private javax.swing.JPanel processUnallocPanel;
|
private javax.swing.JPanel processUnallocPanel;
|
||||||
private javax.swing.JScrollPane servicesScrollPane;
|
|
||||||
private javax.swing.JTable servicesTable;
|
|
||||||
private javax.swing.JPanel simplePanel;
|
private javax.swing.JPanel simplePanel;
|
||||||
private javax.swing.ButtonGroup timeGroup;
|
private javax.swing.ButtonGroup timeGroup;
|
||||||
private javax.swing.JLabel timeLabel;
|
private javax.swing.JLabel timeLabel;
|
||||||
@ -410,11 +406,11 @@ private void timeRadioButton1ActionPerformed(java.awt.event.ActionEvent evt) {//
|
|||||||
private javax.swing.JRadioButton timeRadioButton3;
|
private javax.swing.JRadioButton timeRadioButton3;
|
||||||
// End of variables declaration//GEN-END:variables
|
// End of variables declaration//GEN-END:variables
|
||||||
|
|
||||||
private class ServicesTableModel extends AbstractTableModel {
|
private class ModulesTableModel extends AbstractTableModel {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int getRowCount() {
|
public int getRowCount() {
|
||||||
return services.size();
|
return modules.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -424,9 +420,9 @@ private void timeRadioButton1ActionPerformed(java.awt.event.ActionEvent evt) {//
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Object getValueAt(int rowIndex, int columnIndex) {
|
public Object getValueAt(int rowIndex, int columnIndex) {
|
||||||
String name = services.get(rowIndex).getName();
|
String name = modules.get(rowIndex).getName();
|
||||||
if (columnIndex == 0) {
|
if (columnIndex == 0) {
|
||||||
return serviceStates.get(name);
|
return moduleStates.get(name);
|
||||||
} else {
|
} else {
|
||||||
return name;
|
return name;
|
||||||
}
|
}
|
||||||
@ -440,7 +436,7 @@ private void timeRadioButton1ActionPerformed(java.awt.event.ActionEvent evt) {//
|
|||||||
@Override
|
@Override
|
||||||
public void setValueAt(Object aValue, int rowIndex, int columnIndex) {
|
public void setValueAt(Object aValue, int rowIndex, int columnIndex) {
|
||||||
if (columnIndex == 0) {
|
if (columnIndex == 0) {
|
||||||
serviceStates.put((String) getValueAt(rowIndex, 1), (Boolean) aValue);
|
moduleStates.put((String) getValueAt(rowIndex, 1), (Boolean) aValue);
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -451,15 +447,15 @@ private void timeRadioButton1ActionPerformed(java.awt.event.ActionEvent evt) {//
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
List<IngestServiceAbstract> getServicesToStart() {
|
List<IngestModuleAbstract> getModulesToStart() {
|
||||||
List<IngestServiceAbstract> servicesToStart = new ArrayList<IngestServiceAbstract>();
|
List<IngestModuleAbstract> modulesToStart = new ArrayList<IngestModuleAbstract>();
|
||||||
for (IngestServiceAbstract service : services) {
|
for (IngestModuleAbstract module : modules) {
|
||||||
boolean serviceEnabled = serviceStates.get(service.getName());
|
boolean moduleEnabled = moduleStates.get(module.getName());
|
||||||
if (serviceEnabled) {
|
if (moduleEnabled) {
|
||||||
servicesToStart.add(service);
|
modulesToStart.add(module);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return servicesToStart;
|
return modulesToStart;
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean timeSelectionEnabled() {
|
private boolean timeSelectionEnabled() {
|
||||||
@ -482,8 +478,8 @@ private void timeRadioButton1ActionPerformed(java.awt.event.ActionEvent evt) {//
|
|||||||
|
|
||||||
private void reloadSimpleConfiguration() {
|
private void reloadSimpleConfiguration() {
|
||||||
simplePanel.removeAll();
|
simplePanel.removeAll();
|
||||||
if (currentService.hasSimpleConfiguration()) {
|
if (currentModule.hasSimpleConfiguration()) {
|
||||||
simplePanel.add(currentService.getSimpleConfiguration());
|
simplePanel.add(currentModule.getSimpleConfiguration());
|
||||||
}
|
}
|
||||||
simplePanel.revalidate();
|
simplePanel.revalidate();
|
||||||
simplePanel.repaint();
|
simplePanel.repaint();
|
||||||
@ -495,8 +491,8 @@ private void timeRadioButton1ActionPerformed(java.awt.event.ActionEvent evt) {//
|
|||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public void save() {
|
public void save() {
|
||||||
if (currentService != null && currentService.hasSimpleConfiguration()) {
|
if (currentModule != null && currentModule.hasSimpleConfiguration()) {
|
||||||
currentService.saveSimpleConfiguration();
|
currentModule.saveSimpleConfiguration();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -512,11 +508,11 @@ private void timeRadioButton1ActionPerformed(java.awt.event.ActionEvent evt) {//
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void start() {
|
public void start() {
|
||||||
//pick the services
|
//pick the modules
|
||||||
List<IngestServiceAbstract> servicesToStart = getServicesToStart();
|
List<IngestModuleAbstract> modulesToStart = getModulesToStart();
|
||||||
|
|
||||||
if (!servicesToStart.isEmpty()) {
|
if (!modulesToStart.isEmpty()) {
|
||||||
manager.execute(servicesToStart, image);
|
manager.execute(modulesToStart, image);
|
||||||
}
|
}
|
||||||
|
|
||||||
//update ingest freq. refresh
|
//update ingest freq. refresh
|
||||||
@ -537,9 +533,9 @@ private void timeRadioButton1ActionPerformed(java.awt.event.ActionEvent evt) {//
|
|||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Custom cell renderer for tooltips with service description
|
* Custom cell renderer for tooltips with module description
|
||||||
*/
|
*/
|
||||||
private class ServiceTableRenderer extends DefaultTableCellRenderer {
|
private class ModulesTableRenderer extends DefaultTableCellRenderer {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Component getTableCellRendererComponent(
|
public Component getTableCellRendererComponent(
|
||||||
@ -550,10 +546,10 @@ private void timeRadioButton1ActionPerformed(java.awt.event.ActionEvent evt) {//
|
|||||||
super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);
|
super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);
|
||||||
|
|
||||||
if (column == 1) {
|
if (column == 1) {
|
||||||
//String serviceName = (String) table.getModel().getValueAt(row, column);
|
//String moduleName = (String) table.getModel().getValueAt(row, column);
|
||||||
IngestServiceAbstract service = services.get(row);
|
IngestModuleAbstract module = modules.get(row);
|
||||||
String serviceDescr = service.getDescription();
|
String moduleDescr = module.getDescription();
|
||||||
setToolTipText(serviceDescr);
|
setToolTipText(moduleDescr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -31,42 +31,42 @@ import org.sleuthkit.autopsy.ingest.IngestManager.IngestModuleEvent;
|
|||||||
import org.sleuthkit.datamodel.Image;
|
import org.sleuthkit.datamodel.Image;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* worker for every ingest image service there is a separate instance per image
|
* worker for every ingest image module there is a separate instance per image
|
||||||
* / service pair
|
* / module pair
|
||||||
*/
|
*/
|
||||||
public class IngestImageThread extends SwingWorker<Object, Void> {
|
public class IngestImageThread extends SwingWorker<Object, Void> {
|
||||||
|
|
||||||
private Logger logger = Logger.getLogger(IngestImageThread.class.getName());
|
private Logger logger = Logger.getLogger(IngestImageThread.class.getName());
|
||||||
private ProgressHandle progress;
|
private ProgressHandle progress;
|
||||||
private Image image;
|
private Image image;
|
||||||
private IngestServiceImage service;
|
private IngestModuleImage module;
|
||||||
private IngestImageWorkerController controller;
|
private IngestImageWorkerController controller;
|
||||||
private IngestManager manager;
|
private IngestManager manager;
|
||||||
|
|
||||||
IngestImageThread(IngestManager manager, Image image, IngestServiceImage service) {
|
IngestImageThread(IngestManager manager, Image image, IngestModuleImage module) {
|
||||||
this.manager = manager;
|
this.manager = manager;
|
||||||
this.image = image;
|
this.image = image;
|
||||||
this.service = service;
|
this.module = module;
|
||||||
}
|
}
|
||||||
|
|
||||||
Image getImage() {
|
Image getImage() {
|
||||||
return image;
|
return image;
|
||||||
}
|
}
|
||||||
|
|
||||||
IngestServiceImage getService() {
|
IngestModuleImage getModule() {
|
||||||
return service;
|
return module;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected Object doInBackground() throws Exception {
|
protected Object doInBackground() throws Exception {
|
||||||
|
|
||||||
logger.log(Level.INFO, "Starting processing of service: " + service.getName());
|
logger.log(Level.INFO, "Starting processing of module: " + module.getName());
|
||||||
|
|
||||||
final String displayName = service.getName() + " image id:" + image.getId();
|
final String displayName = module.getName() + " image id:" + image.getId();
|
||||||
progress = ProgressHandleFactory.createHandle(displayName, new Cancellable() {
|
progress = ProgressHandleFactory.createHandle(displayName, new Cancellable() {
|
||||||
@Override
|
@Override
|
||||||
public boolean cancel() {
|
public boolean cancel() {
|
||||||
logger.log(Level.INFO, "Image ingest service " + service.getName() + " cancelled by user.");
|
logger.log(Level.INFO, "Image ingest module " + module.getName() + " cancelled by user.");
|
||||||
if (progress != null) {
|
if (progress != null) {
|
||||||
progress.setDisplayName(displayName + " (Cancelling...)");
|
progress.setDisplayName(displayName + " (Cancelling...)");
|
||||||
}
|
}
|
||||||
@ -80,18 +80,18 @@ public class IngestImageThread extends SwingWorker<Object, Void> {
|
|||||||
controller = new IngestImageWorkerController(this, progress);
|
controller = new IngestImageWorkerController(this, progress);
|
||||||
|
|
||||||
if (isCancelled()) {
|
if (isCancelled()) {
|
||||||
logger.log(Level.INFO, "Terminating image ingest service " + service.getName() + " due to cancellation.");
|
logger.log(Level.INFO, "Terminating image ingest module " + module.getName() + " due to cancellation.");
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
final StopWatch timer = new StopWatch();
|
final StopWatch timer = new StopWatch();
|
||||||
timer.start();
|
timer.start();
|
||||||
try {
|
try {
|
||||||
service.process(image, controller);
|
module.process(image, controller);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
logger.log(Level.WARNING, "Exception in service: " + service.getName() + " image: " + image.getName(), e);
|
logger.log(Level.WARNING, "Exception in module: " + module.getName() + " image: " + image.getName(), e);
|
||||||
} finally {
|
} finally {
|
||||||
timer.stop();
|
timer.stop();
|
||||||
logger.log(Level.INFO, "Done processing of service: " + service.getName()
|
logger.log(Level.INFO, "Done processing of module: " + module.getName()
|
||||||
+ " took " + timer.getElapsedTimeSecs() + " secs. to process()" );
|
+ " took " + timer.getElapsedTimeSecs() + " secs. to process()" );
|
||||||
|
|
||||||
EventQueue.invokeLater(new Runnable() {
|
EventQueue.invokeLater(new Runnable() {
|
||||||
@ -102,27 +102,27 @@ public class IngestImageThread extends SwingWorker<Object, Void> {
|
|||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
//cleanup queues (worker and image/service)
|
//cleanup queues (worker and image/module)
|
||||||
manager.removeImageIngestWorker(this);
|
manager.removeImageIngestWorker(this);
|
||||||
|
|
||||||
if (!this.isCancelled()) {
|
if (!this.isCancelled()) {
|
||||||
logger.log(Level.INFO, "Service " + service.getName() + " completed");
|
logger.log(Level.INFO, "Module " + module.getName() + " completed");
|
||||||
try {
|
try {
|
||||||
service.complete();
|
module.complete();
|
||||||
}
|
}
|
||||||
catch (Exception e) {
|
catch (Exception e) {
|
||||||
logger.log(Level.INFO, "Error completing the service " + service.getName(), e);
|
logger.log(Level.INFO, "Error completing the module " + module.getName(), e);
|
||||||
}
|
}
|
||||||
IngestManager.fireServiceEvent(IngestModuleEvent.COMPLETED.toString(), service.getName());
|
IngestManager.fireModuleEvent(IngestModuleEvent.COMPLETED.toString(), module.getName());
|
||||||
} else {
|
} else {
|
||||||
logger.log(Level.INFO, "Service " + service.getName() + " stopped");
|
logger.log(Level.INFO, "Module " + module.getName() + " stopped");
|
||||||
try {
|
try {
|
||||||
service.stop();
|
module.stop();
|
||||||
}
|
}
|
||||||
catch (Exception e) {
|
catch (Exception e) {
|
||||||
logger.log(Level.INFO, "Error stopping the service" + service.getName(), e);
|
logger.log(Level.INFO, "Error stopping the module" + module.getName(), e);
|
||||||
}
|
}
|
||||||
IngestManager.fireServiceEvent(IngestModuleEvent.STOPPED.toString(), service.getName());
|
IngestManager.fireModuleEvent(IngestModuleEvent.STOPPED.toString(), module.getName());
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -21,8 +21,8 @@ package org.sleuthkit.autopsy.ingest;
|
|||||||
import org.netbeans.api.progress.ProgressHandle;
|
import org.netbeans.api.progress.ProgressHandle;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Controller for image level ingest services
|
* Controller for image level ingest modules
|
||||||
* Used by services to check task status and to post progress to
|
* Used by modules to check task status and to post progress to
|
||||||
*/
|
*/
|
||||||
public class IngestImageWorkerController {
|
public class IngestImageWorkerController {
|
||||||
|
|
||||||
@ -40,8 +40,8 @@ public class IngestImageWorkerController {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Check if the task has been cancelled. This should be polled by the service periodically
|
* Check if the task has been cancelled. This should be polled by the module periodically
|
||||||
* And the service needs to act, i.e. break out of its processing loop and call its stop() to cleanup
|
* And the module needs to act, i.e. break out of its processing loop and call its stop() to cleanup
|
||||||
*
|
*
|
||||||
* @return true if the task has been cancelled, false otherwise
|
* @return true if the task has been cancelled, false otherwise
|
||||||
*/
|
*/
|
||||||
@ -70,7 +70,7 @@ public class IngestImageWorkerController {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Update the progress bar with the number of work units performed, if in the determinate mode
|
* Update the progress bar with the number of work units performed, if in the determinate mode
|
||||||
* @param workUnits number of work units performed so far by the service
|
* @param workUnits number of work units performed so far by the module
|
||||||
*/
|
*/
|
||||||
public void progress(int workUnits) {
|
public void progress(int workUnits) {
|
||||||
if (progress != null) {
|
if (progress != null) {
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -1,94 +0,0 @@
|
|||||||
/*
|
|
||||||
* Autopsy Forensic Browser
|
|
||||||
*
|
|
||||||
* Copyright 2011 Basis Technology Corp.
|
|
||||||
* Contact: carrier <at> sleuthkit <dot> org
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
package org.sleuthkit.autopsy.ingest;
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Ingest manager facade used by ingest services
|
|
||||||
*
|
|
||||||
* Facility for services to interact with the ingest manager
|
|
||||||
* for sending data events, ingest messages, getting configuration, such as
|
|
||||||
* update frequency configuration
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
public class IngestManagerProxy {
|
|
||||||
|
|
||||||
private IngestManager manager;
|
|
||||||
|
|
||||||
IngestManagerProxy(IngestManager manager) {
|
|
||||||
this.manager = manager;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Post ingest message
|
|
||||||
* @param message ingest message to be posted by ingest service
|
|
||||||
*/
|
|
||||||
public void postMessage(final IngestMessage message) {
|
|
||||||
manager.postMessage(message);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Fire service event to notify registered service event listeners
|
|
||||||
* @param eventType the event type, defined in IngestManager.IngestManagerEvents
|
|
||||||
* @param serviceName the service name
|
|
||||||
*/
|
|
||||||
public static void fireServiceEvent(String eventType, String serviceName) {
|
|
||||||
IngestManager.fireServiceEvent(eventType, serviceName);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Fire service data event to notify registered service data event listeners
|
|
||||||
* @param serviceDataEvent service data event, encapsulating blackboard artifact data
|
|
||||||
*/
|
|
||||||
public static void fireServiceDataEvent(ServiceDataEvent serviceDataEvent) {
|
|
||||||
IngestManager.fireServiceDataEvent(serviceDataEvent);;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Facility for the service to query the currently set recommended data update frequency in minutes
|
|
||||||
* Services that post data in controlled time intervals, should obey this setting
|
|
||||||
*
|
|
||||||
* @return max. number of minutes before service posts new data, if data is available
|
|
||||||
*/
|
|
||||||
public int getUpdateFrequency() {
|
|
||||||
return manager.getUpdateFrequency().getTime();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Facility for a file ingest service to check a return value from another file ingest service
|
|
||||||
* that executed for the same file earlier in the file ingest pipeline
|
|
||||||
* The service return value can be used as a guideline to skip processing the file
|
|
||||||
*
|
|
||||||
* @param serviceName registered service name of the service to check the return value of
|
|
||||||
* @return the return value of the previously executed service for the currently processed file in the file ingest pipeline
|
|
||||||
*/
|
|
||||||
public IngestServiceAbstractFile.ProcessResult getAbstractFileServiceResult(String serviceName) {
|
|
||||||
return manager.getAbstractFileServiceResult(serviceName);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
@ -24,7 +24,7 @@ import org.sleuthkit.autopsy.datamodel.KeyValue;
|
|||||||
import org.sleuthkit.datamodel.BlackboardArtifact;
|
import org.sleuthkit.datamodel.BlackboardArtifact;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Representation of subject posted by ingest services
|
* Representation of subject posted by ingest modules
|
||||||
*
|
*
|
||||||
* Message should have a unique ID within context of originating source
|
* Message should have a unique ID within context of originating source
|
||||||
*
|
*
|
||||||
@ -37,7 +37,7 @@ public class IngestMessage {
|
|||||||
};
|
};
|
||||||
private long ID;
|
private long ID;
|
||||||
private MessageType messageType;
|
private MessageType messageType;
|
||||||
private IngestServiceAbstract source;
|
private IngestModuleAbstract source;
|
||||||
private String subject;
|
private String subject;
|
||||||
private String detailsHtml;
|
private String detailsHtml;
|
||||||
private String uniqueKey;
|
private String uniqueKey;
|
||||||
@ -46,7 +46,7 @@ public class IngestMessage {
|
|||||||
private static SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
|
private static SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
|
||||||
private static int managerMessageId = 0;
|
private static int managerMessageId = 0;
|
||||||
|
|
||||||
private IngestMessage(long ID, MessageType messageType, IngestServiceAbstract source, String subject, String detailsHtml, String uniqueKey) {
|
private IngestMessage(long ID, MessageType messageType, IngestModuleAbstract source, String subject, String detailsHtml, String uniqueKey) {
|
||||||
this.ID = ID;
|
this.ID = ID;
|
||||||
this.source = source;
|
this.source = source;
|
||||||
this.messageType = messageType;
|
this.messageType = messageType;
|
||||||
@ -63,7 +63,7 @@ public class IngestMessage {
|
|||||||
return ID;
|
return ID;
|
||||||
}
|
}
|
||||||
|
|
||||||
public IngestServiceAbstract getSource() {
|
public IngestModuleAbstract getSource() {
|
||||||
return source;
|
return source;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -163,12 +163,12 @@ public class IngestMessage {
|
|||||||
* Create a simple message with a subject only
|
* Create a simple message with a subject only
|
||||||
* @param ID ID of the message, unique in the context of module that generated it
|
* @param ID ID of the message, unique in the context of module that generated it
|
||||||
* @param messageType message type
|
* @param messageType message type
|
||||||
* @param source originating service
|
* @param source originating module
|
||||||
* @param subject message subject to be displayed
|
* @param subject message subject to be displayed
|
||||||
* @param details message details to be displayed, or null
|
* @param details message details to be displayed, or null
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
public static IngestMessage createMessage(long ID, MessageType messageType, IngestServiceAbstract source, String subject, String details) {
|
public static IngestMessage createMessage(long ID, MessageType messageType, IngestModuleAbstract source, String subject, String details) {
|
||||||
if (messageType == null || source == null || subject == null) {
|
if (messageType == null || source == null || subject == null) {
|
||||||
throw new IllegalArgumentException("message type, source and subject cannot be null");
|
throw new IllegalArgumentException("message type, source and subject cannot be null");
|
||||||
}
|
}
|
||||||
@ -179,11 +179,11 @@ public class IngestMessage {
|
|||||||
* Create a simple message with a subject only
|
* Create a simple message with a subject only
|
||||||
* @param ID ID of the message, unique in the context of module that generated it
|
* @param ID ID of the message, unique in the context of module that generated it
|
||||||
* @param messageType message type
|
* @param messageType message type
|
||||||
* @param source originating service
|
* @param source originating module
|
||||||
* @param subject message subject to be displayed
|
* @param subject message subject to be displayed
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
public static IngestMessage createMessage(long ID, MessageType messageType, IngestServiceAbstract source, String subject) {
|
public static IngestMessage createMessage(long ID, MessageType messageType, IngestModuleAbstract source, String subject) {
|
||||||
return createMessage(ID, messageType, source, subject, null);
|
return createMessage(ID, messageType, source, subject, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -191,12 +191,12 @@ public class IngestMessage {
|
|||||||
/**
|
/**
|
||||||
* Create error message
|
* Create error message
|
||||||
* @param ID ID of the message, unique in the context of module that generated it
|
* @param ID ID of the message, unique in the context of module that generated it
|
||||||
* @param source originating service
|
* @param source originating module
|
||||||
* @param subject message subject to be displayed
|
* @param subject message subject to be displayed
|
||||||
* @param details message details to be displayed, or null
|
* @param details message details to be displayed, or null
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
public static IngestMessage createErrorMessage(long ID, IngestServiceAbstract source, String subject, String details) {
|
public static IngestMessage createErrorMessage(long ID, IngestModuleAbstract source, String subject, String details) {
|
||||||
if (source == null || subject == null) {
|
if (source == null || subject == null) {
|
||||||
throw new IllegalArgumentException("source and subject cannot be null");
|
throw new IllegalArgumentException("source and subject cannot be null");
|
||||||
}
|
}
|
||||||
@ -206,12 +206,12 @@ public class IngestMessage {
|
|||||||
/**
|
/**
|
||||||
* Create warning message
|
* Create warning message
|
||||||
* @param ID ID of the message, unique in the context of module that generated it
|
* @param ID ID of the message, unique in the context of module that generated it
|
||||||
* @param source originating service
|
* @param source originating module
|
||||||
* @param subject message subject to be displayed
|
* @param subject message subject to be displayed
|
||||||
* @param details message details to be displayed, or null
|
* @param details message details to be displayed, or null
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
public static IngestMessage createWarningMessage(long ID, IngestServiceAbstract source, String subject, String details) {
|
public static IngestMessage createWarningMessage(long ID, IngestModuleAbstract source, String subject, String details) {
|
||||||
if (source == null || subject == null) {
|
if (source == null || subject == null) {
|
||||||
throw new IllegalArgumentException("source and subject cannot be null");
|
throw new IllegalArgumentException("source and subject cannot be null");
|
||||||
}
|
}
|
||||||
@ -221,14 +221,14 @@ public class IngestMessage {
|
|||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @param ID ID of the message, unique in the context of module that generated it
|
* @param ID ID of the message, unique in the context of module that generated it
|
||||||
* @param source originating service
|
* @param source originating module
|
||||||
* @param subject message subject to be displayed
|
* @param subject message subject to be displayed
|
||||||
* @param detailsHtml html formatted detailed message (without leading and closing <html> tags), for instance, a human-readable representation of the data.
|
* @param detailsHtml html formatted detailed message (without leading and closing <html> tags), for instance, a human-readable representation of the data.
|
||||||
* @param uniqueKey unique key determining uniqueness of the message, or null. Helps grouping similar messages and determine their importance. Subsequent messages with the same uniqueKey will be treated with lower priority.
|
* @param uniqueKey unique key determining uniqueness of the message, or null. Helps grouping similar messages and determine their importance. Subsequent messages with the same uniqueKey will be treated with lower priority.
|
||||||
* @param data data blackboard artifact associated with the message, the same as fired in ServiceDataEvent by the service
|
* @param data data blackboard artifact associated with the message, the same as fired in ModuleDataEvent by the module
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
public static IngestMessage createDataMessage(long ID, IngestServiceAbstract source, String subject, String detailsHtml, String uniqueKey, BlackboardArtifact data) {
|
public static IngestMessage createDataMessage(long ID, IngestModuleAbstract source, String subject, String detailsHtml, String uniqueKey, BlackboardArtifact data) {
|
||||||
if (source == null || subject == null || detailsHtml == null || data == null) {
|
if (source == null || subject == null || detailsHtml == null || data == null) {
|
||||||
throw new IllegalArgumentException("source, subject, details and data cannot be null");
|
throw new IllegalArgumentException("source, subject, details and data cannot be null");
|
||||||
}
|
}
|
||||||
|
@ -45,7 +45,7 @@ import org.sleuthkit.autopsy.ingest.IngestMessage.*;
|
|||||||
import org.sleuthkit.datamodel.BlackboardArtifact;
|
import org.sleuthkit.datamodel.BlackboardArtifact;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Notification window showing messages from services to user
|
* Notification window showing messages from modules to user
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
class IngestMessagePanel extends javax.swing.JPanel {
|
class IngestMessagePanel extends javax.swing.JPanel {
|
||||||
@ -62,7 +62,7 @@ class IngestMessagePanel extends javax.swing.JPanel {
|
|||||||
|
|
||||||
private enum COLUMN {
|
private enum COLUMN {
|
||||||
|
|
||||||
SUBJECT, COUNT, SERVICE
|
SUBJECT, COUNT, MODULE
|
||||||
};
|
};
|
||||||
private static PropertyChangeSupport messagePcs = new PropertyChangeSupport(IngestMessagePanel.class);
|
private static PropertyChangeSupport messagePcs = new PropertyChangeSupport(IngestMessagePanel.class);
|
||||||
static final String MESSAGE_CHANGE_EVT = "MESSAGE_CHANGE_EVT"; //number of unread messages changed
|
static final String MESSAGE_CHANGE_EVT = "MESSAGE_CHANGE_EVT"; //number of unread messages changed
|
||||||
@ -320,10 +320,10 @@ class IngestMessagePanel extends javax.swing.JPanel {
|
|||||||
//data
|
//data
|
||||||
|
|
||||||
private List<TableEntry> messageData = new ArrayList<TableEntry>();
|
private List<TableEntry> messageData = new ArrayList<TableEntry>();
|
||||||
//for keeping track of messages to group, per service, by uniqness
|
//for keeping track of messages to group, per module, by uniqness
|
||||||
private Map<IngestServiceAbstract, Map<String, List<IngestMessageGroup>>> groupings = new HashMap<IngestServiceAbstract, Map<String, List<IngestMessageGroup>>>();
|
private Map<IngestModuleAbstract, Map<String, List<IngestMessageGroup>>> groupings = new HashMap<IngestModuleAbstract, Map<String, List<IngestMessageGroup>>>();
|
||||||
private boolean chronoSort = true; //chronological sort default
|
private boolean chronoSort = true; //chronological sort default
|
||||||
private static final int MESSAGE_GROUP_THRESH = 3; //group messages after 3 messages per service with same uniqness
|
private static final int MESSAGE_GROUP_THRESH = 3; //group messages after 3 messages per module with same uniqness
|
||||||
private Logger logger = Logger.getLogger(MessageTableModel.class.getName());
|
private Logger logger = Logger.getLogger(MessageTableModel.class.getName());
|
||||||
|
|
||||||
MessageTableModel() {
|
MessageTableModel() {
|
||||||
@ -331,12 +331,12 @@ class IngestMessagePanel extends javax.swing.JPanel {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void init() {
|
private void init() {
|
||||||
//initialize groupings map with services
|
//initialize groupings map with modules
|
||||||
for (IngestServiceAbstract service : IngestManager.enumerateAbstractFileServices()) {
|
for (IngestModuleAbstract module : IngestManager.enumerateAbstractFileModules()) {
|
||||||
groupings.put(service, new HashMap<String, List<IngestMessageGroup>>());
|
groupings.put(module, new HashMap<String, List<IngestMessageGroup>>());
|
||||||
}
|
}
|
||||||
for (IngestServiceAbstract service : IngestManager.enumerateImageServices()) {
|
for (IngestModuleAbstract module : IngestManager.enumerateImageModules()) {
|
||||||
groupings.put(service, new HashMap<String, List<IngestMessageGroup>>());
|
groupings.put(module, new HashMap<String, List<IngestMessageGroup>>());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -418,8 +418,8 @@ class IngestMessagePanel extends javax.swing.JPanel {
|
|||||||
|
|
||||||
switch (columnIndex) {
|
switch (columnIndex) {
|
||||||
case 0:
|
case 0:
|
||||||
Object service = entry.messageGroup.getSource();
|
Object module = entry.messageGroup.getSource();
|
||||||
if (service == null) {
|
if (module == null) {
|
||||||
ret = "";
|
ret = "";
|
||||||
} else {
|
} else {
|
||||||
ret = (Object) entry.messageGroup.getSource().getName();
|
ret = (Object) entry.messageGroup.getSource().getName();
|
||||||
@ -462,13 +462,13 @@ class IngestMessagePanel extends javax.swing.JPanel {
|
|||||||
}
|
}
|
||||||
|
|
||||||
synchronized public void addMessage(IngestMessage m) {
|
synchronized public void addMessage(IngestMessage m) {
|
||||||
//check how many messages per service with the same uniqness
|
//check how many messages per module with the same uniqness
|
||||||
//and add to existing group or create a new group
|
//and add to existing group or create a new group
|
||||||
IngestServiceAbstract service = m.getSource();
|
IngestModuleAbstract module = m.getSource();
|
||||||
IngestMessageGroup messageGroup = null;
|
IngestMessageGroup messageGroup = null;
|
||||||
if (service != null && m.getMessageType() == IngestMessage.MessageType.DATA) {
|
if (module != null && m.getMessageType() == IngestMessage.MessageType.DATA) {
|
||||||
//not a manager message, a data message, then group
|
//not a manager message, a data message, then group
|
||||||
final Map<String, List<IngestMessageGroup>> groups = groupings.get(service);
|
final Map<String, List<IngestMessageGroup>> groups = groupings.get(module);
|
||||||
//groups for this uniqueness
|
//groups for this uniqueness
|
||||||
final String uniqueness = m.getUniqueKey();
|
final String uniqueness = m.getUniqueKey();
|
||||||
List<IngestMessageGroup> uniqGroups = groups.get(uniqueness);
|
List<IngestMessageGroup> uniqGroups = groups.get(uniqueness);
|
||||||
@ -732,9 +732,9 @@ class IngestMessagePanel extends javax.swing.JPanel {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* return source service, should be the same for all msgs
|
* return source module, should be the same for all msgs
|
||||||
*/
|
*/
|
||||||
IngestServiceAbstract getSource() {
|
IngestModuleAbstract getSource() {
|
||||||
return messages.get(0).getSource();
|
return messages.get(0).getSource();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -280,7 +280,7 @@ public final class IngestMessageTopComponent extends TopComponent implements Ing
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Display IngestMessage from service (forwarded by IngestManager)
|
* Display IngestMessage from module (forwarded by IngestManager)
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public void displayMessage(IngestMessage ingestMessage) {
|
public void displayMessage(IngestMessage ingestMessage) {
|
||||||
|
@ -16,17 +16,12 @@
|
|||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
package org.sleuthkit.autopsy.ingest;
|
package org.sleuthkit.autopsy.ingest;
|
||||||
|
|
||||||
import java.awt.Component;
|
import java.awt.Component;
|
||||||
import java.awt.event.ActionEvent;
|
import java.awt.event.ActionEvent;
|
||||||
import javax.swing.AbstractAction;
|
import javax.swing.AbstractAction;
|
||||||
import org.openide.util.actions.Presenter;
|
import org.openide.util.actions.Presenter;
|
||||||
import org.openide.windows.Mode;
|
|
||||||
import org.openide.windows.WindowManager;
|
|
||||||
|
|
||||||
|
|
||||||
//@ActionID(category = "File",
|
//@ActionID(category = "File",
|
||||||
//id = "org.sleuthkit.autopsy.ingest.IngestMessagesAction")
|
//id = "org.sleuthkit.autopsy.ingest.IngestMessagesAction")
|
||||||
@ -40,11 +35,10 @@ public final class IngestMessagesAction extends AbstractAction implements Prese
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void actionPerformed(ActionEvent e) {
|
public void actionPerformed(ActionEvent e) {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Component getToolbarPresenter() {
|
public Component getToolbarPresenter() {
|
||||||
return new IngestMessagesToolbar();
|
return IngestMessagesToolbar.getDefault();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
<?xml version="1.1" encoding="UTF-8" ?>
|
<?xml version="1.0" encoding="UTF-8" ?>
|
||||||
|
|
||||||
<Form version="1.5" maxVersion="1.7" type="org.netbeans.modules.form.forminfo.JPanelFormInfo">
|
<Form version="1.5" maxVersion="1.7" type="org.netbeans.modules.form.forminfo.JPanelFormInfo">
|
||||||
<Properties>
|
<Properties>
|
||||||
|
@ -37,17 +37,30 @@ import org.sleuthkit.autopsy.casemodule.Case;
|
|||||||
public class IngestMessagesToolbar extends javax.swing.JPanel {
|
public class IngestMessagesToolbar extends javax.swing.JPanel {
|
||||||
|
|
||||||
private IngestMessagesButton ingestMessagesButton = new IngestMessagesButton();
|
private IngestMessagesButton ingestMessagesButton = new IngestMessagesButton();
|
||||||
|
private static IngestMessagesToolbar instance;
|
||||||
|
|
||||||
/** Creates new form IngestMessagesToolbar */
|
/**
|
||||||
public IngestMessagesToolbar() {
|
* Creates new form IngestMessagesToolbar
|
||||||
|
*/
|
||||||
|
private IngestMessagesToolbar() {
|
||||||
initComponents();
|
initComponents();
|
||||||
customizeComponents();
|
customizeComponents();
|
||||||
}
|
}
|
||||||
|
|
||||||
/** This method is called from within the constructor to
|
/**
|
||||||
* initialize the form.
|
* @return the default instance IngestMessagesToolbar
|
||||||
* WARNING: Do NOT modify this code. The content of this method is
|
*/
|
||||||
* always regenerated by the Form Editor.
|
public static IngestMessagesToolbar getDefault() {
|
||||||
|
if (instance == null) {
|
||||||
|
instance = new IngestMessagesToolbar();
|
||||||
|
}
|
||||||
|
return instance;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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")
|
@SuppressWarnings("unchecked")
|
||||||
// <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
|
// <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
|
||||||
@ -82,7 +95,6 @@ public class IngestMessagesToolbar extends javax.swing.JPanel {
|
|||||||
ingestMessagesButton.setMinimumSize(new java.awt.Dimension(38, 24));
|
ingestMessagesButton.setMinimumSize(new java.awt.Dimension(38, 24));
|
||||||
ingestMessagesButton.setPreferredSize(new java.awt.Dimension(38, 24));
|
ingestMessagesButton.setPreferredSize(new java.awt.Dimension(38, 24));
|
||||||
ingestMessagesButton.addActionListener(new java.awt.event.ActionListener() {
|
ingestMessagesButton.addActionListener(new java.awt.event.ActionListener() {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void actionPerformed(java.awt.event.ActionEvent evt) {
|
public void actionPerformed(java.awt.event.ActionEvent evt) {
|
||||||
showIngestMessages();
|
showIngestMessages();
|
||||||
@ -98,7 +110,6 @@ public class IngestMessagesToolbar extends javax.swing.JPanel {
|
|||||||
this.setBorder(null);
|
this.setBorder(null);
|
||||||
|
|
||||||
IngestMessagePanel.addPropertyChangeSupportListener(new PropertyChangeListener() {
|
IngestMessagePanel.addPropertyChangeSupportListener(new PropertyChangeListener() {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void propertyChange(PropertyChangeEvent evt) {
|
public void propertyChange(PropertyChangeEvent evt) {
|
||||||
final int numberMessages = (Integer) evt.getNewValue();
|
final int numberMessages = (Integer) evt.getNewValue();
|
||||||
@ -110,7 +121,6 @@ public class IngestMessagesToolbar extends javax.swing.JPanel {
|
|||||||
});
|
});
|
||||||
|
|
||||||
Case.addPropertyChangeListener(new PropertyChangeListener() {
|
Case.addPropertyChangeListener(new PropertyChangeListener() {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void propertyChange(PropertyChangeEvent evt) {
|
public void propertyChange(PropertyChangeEvent evt) {
|
||||||
if (evt.getPropertyName().equals(Case.CASE_CURRENT_CASE)) {
|
if (evt.getPropertyName().equals(Case.CASE_CURRENT_CASE)) {
|
||||||
@ -140,7 +150,6 @@ public class IngestMessagesToolbar extends javax.swing.JPanel {
|
|||||||
|
|
||||||
private static class IngestMessagesButton extends JButton {
|
private static class IngestMessagesButton extends JButton {
|
||||||
|
|
||||||
|
|
||||||
private static final int fontSize = 9;
|
private static final int fontSize = 9;
|
||||||
private static final Font messagesFont = new java.awt.Font("Tahoma", Font.PLAIN, fontSize);
|
private static final Font messagesFont = new java.awt.Font("Tahoma", Font.PLAIN, fontSize);
|
||||||
private int messages = 0;
|
private int messages = 0;
|
||||||
@ -149,8 +158,9 @@ public class IngestMessagesToolbar extends javax.swing.JPanel {
|
|||||||
public void paint(Graphics g) {
|
public void paint(Graphics g) {
|
||||||
super.paint(g);
|
super.paint(g);
|
||||||
|
|
||||||
if (messages == 0)
|
if (messages == 0) {
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
//paint text
|
//paint text
|
||||||
String messageStr = Integer.toString(messages);
|
String messageStr = Integer.toString(messages);
|
||||||
final int len = messageStr.length();
|
final int len = messageStr.length();
|
||||||
@ -158,13 +168,14 @@ public class IngestMessagesToolbar extends javax.swing.JPanel {
|
|||||||
|
|
||||||
int dx = len * 5 + 5;
|
int dx = len * 5 + 5;
|
||||||
int x = getSize().width - dx;
|
int x = getSize().width - dx;
|
||||||
if (x<0)
|
if (x < 0) {
|
||||||
x = 0;
|
x = 0;
|
||||||
|
}
|
||||||
g.setColor(Color.GRAY);
|
g.setColor(Color.GRAY);
|
||||||
//g.fillRect(x, 1, dx, fontSize);
|
//g.fillRect(x, 1, dx, fontSize);
|
||||||
g.fillRoundRect(x, 1, dx, fontSize, 2, 2);
|
g.fillRoundRect(x, 1, dx, fontSize, 2, 2);
|
||||||
g.setColor(Color.WHITE);
|
g.setColor(Color.WHITE);
|
||||||
g.drawString(messageStr, x+2, fontSize);
|
g.drawString(messageStr, x + 2, fontSize);
|
||||||
}
|
}
|
||||||
|
|
||||||
void setMessages(int messages) {
|
void setMessages(int messages) {
|
||||||
|
@ -21,75 +21,77 @@ package org.sleuthkit.autopsy.ingest;
|
|||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Base interface for ingest services
|
* Base interface for ingest modules
|
||||||
*/
|
*/
|
||||||
public interface IngestServiceAbstract {
|
public interface IngestModuleAbstract {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Possible service types for the implementing classes
|
* Possible module types for the implementing classes
|
||||||
*/
|
*/
|
||||||
public enum ServiceType {
|
public enum ModuleType {
|
||||||
/**
|
/**
|
||||||
* Image type service
|
* Image type module
|
||||||
*/
|
*/
|
||||||
Image,
|
Image,
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* AbstractFile type service
|
* AbstractFile type module
|
||||||
*/
|
*/
|
||||||
AbstractFile
|
AbstractFile
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Notification from manager that brand new ingest should be initiated.
|
* Notification from manager that brand new ingest should be initiated..
|
||||||
* Service loads its configuration and performs initialization
|
* Module loads its configuration and performs initialization.
|
||||||
* Invoked once per new worker thread, per ingest
|
* Invoked once per new worker thread, per ingest.
|
||||||
*
|
* In this method initialize always IngestServices handle
|
||||||
* @param managerProxy manager facade that can be used by the service to communicate with the manager, e.g.
|
* using IngestServices.getDefault() lazy-loading approach.
|
||||||
* for posting messages, getting configurations
|
* NEVER initialize IngestServices handle in the member declaration, because it might result
|
||||||
|
* in multiple instances of the singleton -- different class loaders are used in different modules.
|
||||||
|
* @param initContext context used to initialize some modules
|
||||||
*/
|
*/
|
||||||
public void init(IngestManagerProxy managerProxy);
|
public void init(IngestModuleInit initContext);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Notification from manager that there is no more content to process and all work is done.
|
* Notification from manager that there is no more content to process and all work is done.
|
||||||
* Service performs any clean-up of internal resources, and finalizes processing to produce complete result
|
* Module performs any clean-up of internal resources, and finalizes processing to produce complete result
|
||||||
* Service also posts ingest message indicating it is done, and posts ingest stats and errors in the details of the message.
|
* Module also posts ingest message indicating it is done, and posts ingest stats and errors in the details of the message.
|
||||||
*/
|
*/
|
||||||
public void complete();
|
public void complete();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Notification from manager to stop processing due to some interruption (user, error, exception)
|
* Notification from manager to stop processing due to some interruption (user, error, exception)
|
||||||
* Service performs any clean-up of internal resources
|
* Module performs any clean-up of internal resources
|
||||||
* It may also discard any pending results, but it should ensure it is in a defined state so that ingest can be rerun later.
|
* It may also discard any pending results, but it should ensure it is in a defined state so that ingest can be rerun later.
|
||||||
*/
|
*/
|
||||||
public void stop();
|
public void stop();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets specific name of the service
|
* Gets specific name of the module
|
||||||
* The name should be unique across services
|
* The name should be unique across modules
|
||||||
* @return unique service name
|
* @return unique module name
|
||||||
*/
|
*/
|
||||||
public String getName();
|
public String getName();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets user-friendly description of the service
|
* Gets user-friendly description of the module
|
||||||
* @return service description
|
* @return module description
|
||||||
*/
|
*/
|
||||||
public String getDescription();
|
public String getDescription();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns type of the service
|
* Returns type of the module
|
||||||
* @return service type
|
* @return module type
|
||||||
*/
|
*/
|
||||||
public ServiceType getType();
|
public ModuleType getType();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A service can manage and use additional threads to perform some work in the background.
|
* A module can manage and use additional threads to perform some work in the background.
|
||||||
* This method provides insight to the manager if the service has truly completed its work or not.
|
* This method provides insight to the manager if the module has truly completed its work or not.
|
||||||
*
|
*
|
||||||
*
|
*
|
||||||
* @return true if any background threads/workers managed by this service are still running or are pending to be run,
|
* @return true if any background threads/workers managed by this module are still running or are pending to be run,
|
||||||
* false if all work has been done, or if background threads are not used/managed by this service
|
* false if all work has been done, or if background threads are not used/managed by this module
|
||||||
*/
|
*/
|
||||||
public boolean hasBackgroundJobsRunning();
|
public boolean hasBackgroundJobsRunning();
|
||||||
|
|
||||||
@ -98,7 +100,7 @@ public interface IngestServiceAbstract {
|
|||||||
* Used to determine if a module has implemented a simple (run-time)
|
* Used to determine if a module has implemented a simple (run-time)
|
||||||
* configuration panel that is displayed by the ingest manager.
|
* configuration panel that is displayed by the ingest manager.
|
||||||
*
|
*
|
||||||
* @return true if this service has a simple (run-time) configuration
|
* @return true if this module has a simple (run-time) configuration
|
||||||
*/
|
*/
|
||||||
public boolean hasSimpleConfiguration();
|
public boolean hasSimpleConfiguration();
|
||||||
|
|
||||||
@ -106,7 +108,7 @@ public interface IngestServiceAbstract {
|
|||||||
* Used to determine if a module has implemented an advanced (general)
|
* Used to determine if a module has implemented an advanced (general)
|
||||||
* configuration that can be used for more in-depth module configuration.
|
* configuration that can be used for more in-depth module configuration.
|
||||||
*
|
*
|
||||||
* @return true if this service has an advanced configuration
|
* @return true if this module has an advanced configuration
|
||||||
*/
|
*/
|
||||||
public boolean hasAdvancedConfiguration();
|
public boolean hasAdvancedConfiguration();
|
||||||
|
|
@ -21,25 +21,23 @@ package org.sleuthkit.autopsy.ingest;
|
|||||||
import org.sleuthkit.datamodel.AbstractFile;
|
import org.sleuthkit.datamodel.AbstractFile;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Ingest service interface that will be called for every file in the image
|
* Ingest module interface that will be called for every file in the image
|
||||||
*/
|
*/
|
||||||
public interface IngestServiceAbstractFile extends IngestServiceAbstract {
|
public interface IngestModuleAbstractFile extends IngestModuleAbstract {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return value resulting from processing AbstractFile
|
* Return value resulting from processing AbstractFile
|
||||||
* Can be used by IngestManager to stop processing the file, or by subsequent module
|
* If ERROR, can be used subsequent module
|
||||||
* in the pipeline as a hint to stop processing the file
|
* in the pipeline as a hint to stop processing the file
|
||||||
*/
|
*/
|
||||||
public enum ProcessResult {
|
public enum ProcessResult {
|
||||||
OK, ///< Indicates that processing was successful (including if the file was largely ignored by the module)
|
OK, ///< Indicates that processing was successful (including if the file was largely ignored by the module)
|
||||||
COND_STOP, ///< Indicates that the module thinks that the pipeline could stop processing, but it is up to the IngestManager to decide. Use this, for example, if a hash lookup detects that a file is known to be good and can be ignored.
|
|
||||||
STOP, ///< Indicates that the module thinks that the pipeline processing should be stopped unconditionally for the current file (this should be used sparingly for critical system errors and could be removed in future version)
|
|
||||||
ERROR, ///< Indicates that an error was encountered while processing the file, hint for later modules that depend on this module to skip processing the file due to error condition (such as file could not be read)
|
ERROR, ///< Indicates that an error was encountered while processing the file, hint for later modules that depend on this module to skip processing the file due to error condition (such as file could not be read)
|
||||||
UNKNOWN ///< Indicates that a return value for the module is not known. This should not be returned directly by modules, but is used when modules want to learn about a return value from a previously run module.
|
UNKNOWN ///< Indicates that a return value for the module is not known. This should not be returned directly by modules, but is used to indicate the module has not set its return value (e.g. it never ran)
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Entry point to process file / directory by the service. See \ref ingestmodule_making for details
|
* Entry point to process file / directory by the module. See \ref ingestmodule_making for details
|
||||||
* on what modules are responsible for doing.
|
* on what modules are responsible for doing.
|
||||||
*
|
*
|
||||||
* @param abstractFile file to process
|
* @param abstractFile file to process
|
@ -22,26 +22,26 @@ import org.sleuthkit.datamodel.Image;
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* Ingest service that acts on entire image
|
* Ingest module that acts on entire image
|
||||||
* Image ingest services run each in its own background thread
|
* Image ingest modules run each in its own background thread
|
||||||
* in parallel to the file processing ingest pipeline and other image ingest modules
|
* in parallel to the file processing ingest pipeline and other image ingest modules
|
||||||
*/
|
*/
|
||||||
public interface IngestServiceImage extends IngestServiceAbstract {
|
public interface IngestModuleImage extends IngestModuleAbstract {
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Entry point to process the image by the service.
|
* Entry point to process the image by the module.
|
||||||
*
|
*
|
||||||
* Service does all the processing work in this method.
|
* Module does all the processing work in this method.
|
||||||
* It is responsible for extracting content of interest from the image (i.e. using DataModel API) and processing it.
|
* It is responsible for extracting content of interest from the image (i.e. using DataModel API) and processing it.
|
||||||
* Results of processing, such as extracted data or analysis results, should be posted to the blackboard.
|
* Results of processing, such as extracted data or analysis results, should be posted to the blackboard.
|
||||||
*
|
*
|
||||||
* The service notifies the ingest inbox of interesting events (data, errors, warnings, infos)
|
* The module notifies the ingest inbox of interesting events (data, errors, warnings, infos)
|
||||||
* by posting ingest messages
|
* by posting ingest messages
|
||||||
* The service notifies data viewers by firing events using IngestManager.fireServiceDataEvent
|
* The module notifies data viewers by firing events using IngestManagerProxy.fireModuleDataEvent
|
||||||
*
|
*
|
||||||
* The service is responsible for posting progress to controller
|
* The module is responsible for posting progress to controller
|
||||||
* And to periodically check controller if it should break out of the processing loop because task has been cancelled
|
* And to periodically check controller if it should break out of the processing loop because task has been canceled
|
||||||
*
|
*
|
||||||
* @param image to process
|
* @param image to process
|
||||||
* @param controller to post progress to and to use for checking if cancellation has occurred
|
* @param controller to post progress to and to use for checking if cancellation has occurred
|
@ -0,0 +1,49 @@
|
|||||||
|
/*
|
||||||
|
* Autopsy Forensic Browser
|
||||||
|
*
|
||||||
|
* Copyright 2012 Basis Technology Corp.
|
||||||
|
* Contact: carrier <at> sleuthkit <dot> org
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package org.sleuthkit.autopsy.ingest;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* Context passed to a module at initialization time.
|
||||||
|
* It may contain module configuration required to initialize some modules.
|
||||||
|
*/
|
||||||
|
public class IngestModuleInit {
|
||||||
|
|
||||||
|
private String moduleArgs;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get module arguments
|
||||||
|
* @return module args string, used by some modules
|
||||||
|
*/
|
||||||
|
public String getModuleArgs() {
|
||||||
|
return moduleArgs;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets module args. string (only used by module pipeline)
|
||||||
|
* @param moduleArgs arguments to set for the module
|
||||||
|
*/
|
||||||
|
void setModuleArgs(String moduleArgs) {
|
||||||
|
this.moduleArgs = moduleArgs;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
107
Ingest/src/org/sleuthkit/autopsy/ingest/IngestServices.java
Normal file
107
Ingest/src/org/sleuthkit/autopsy/ingest/IngestServices.java
Normal file
@ -0,0 +1,107 @@
|
|||||||
|
/*
|
||||||
|
* Autopsy Forensic Browser
|
||||||
|
*
|
||||||
|
* Copyright 2011 Basis Technology Corp.
|
||||||
|
* Contact: carrier <at> sleuthkit <dot> org
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
package org.sleuthkit.autopsy.ingest;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Services available to ingest modules via singleton instance,
|
||||||
|
* e.g. for interacting with the ingest manager
|
||||||
|
* for sending data events, ingest messages, getting configurations, etc.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public class IngestServices {
|
||||||
|
|
||||||
|
private IngestManager manager;
|
||||||
|
|
||||||
|
private static IngestServices instance;
|
||||||
|
|
||||||
|
private IngestServices() {
|
||||||
|
this.manager = IngestManager.getDefault();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get handle to module services
|
||||||
|
* @return the services handle
|
||||||
|
*/
|
||||||
|
public static synchronized IngestServices getDefault() {
|
||||||
|
if (instance == null) {
|
||||||
|
instance = new IngestServices();
|
||||||
|
}
|
||||||
|
return instance;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Post ingest message
|
||||||
|
* @param message ingest message to be posted by ingest module
|
||||||
|
*/
|
||||||
|
public void postMessage(final IngestMessage message) {
|
||||||
|
manager.postMessage(message);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Fire module event to notify registered module event listeners
|
||||||
|
* @param eventType the event type, defined in IngestManager.IngestManagerEvents
|
||||||
|
* @param moduleName the module name
|
||||||
|
*/
|
||||||
|
public void fireModuleEvent(String eventType, String moduleName) {
|
||||||
|
IngestManager.fireModuleEvent(eventType, moduleName);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Fire module data event to notify registered module data event listeners
|
||||||
|
* @param moduleDataEvent module data event, encapsulating blackboard artifact data
|
||||||
|
*/
|
||||||
|
public void fireModuleDataEvent(ModuleDataEvent moduleDataEvent) {
|
||||||
|
IngestManager.fireModuleDataEvent(moduleDataEvent);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Facility for the module to query the currently set recommended data update frequency in minutes
|
||||||
|
* Modules that post data in controlled time intervals, should obey this setting
|
||||||
|
*
|
||||||
|
* @return max. number of minutes before module posts new data, if data is available
|
||||||
|
*
|
||||||
|
* @Deprecated individual modules are be responsible for maintaining such settings
|
||||||
|
*/
|
||||||
|
public int getUpdateFrequency() {
|
||||||
|
return manager.getUpdateFrequency().getTime();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Facility for a file ingest module to check a return value from another file ingest module
|
||||||
|
* that executed for the same file earlier in the file ingest pipeline
|
||||||
|
* The module return value can be used as a guideline to skip processing the file
|
||||||
|
*
|
||||||
|
* @param moduleName registered module name of the module to check the return value of
|
||||||
|
* @return the return value of the previously executed module for the currently processed file in the file ingest pipeline
|
||||||
|
*/
|
||||||
|
public IngestModuleAbstractFile.ProcessResult getAbstractFileModuleResult(String moduleName) {
|
||||||
|
return manager.getAbstractFileModuleResult(moduleName);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
@ -38,6 +38,7 @@ public class Installer extends ModuleInstall {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
|
//at this point UI top component is present for sure, ensure manager has it
|
||||||
manager.initUI();
|
manager.initUI();
|
||||||
//force ingest inbox closed, even if previous state was open
|
//force ingest inbox closed, even if previous state was open
|
||||||
//IngestMessageTopComponent.findInstance().close();
|
//IngestMessageTopComponent.findInstance().close();
|
||||||
|
@ -32,33 +32,33 @@ import org.sleuthkit.datamodel.BlackboardArtifact.ARTIFACT_TYPE;
|
|||||||
* The object wraps a collection of blackboard artifacts and their associated attributes that are to be reported as the new data to listeners.
|
* The object wraps a collection of blackboard artifacts and their associated attributes that are to be reported as the new data to listeners.
|
||||||
* Passing the data as part of the event reduces memory footprint and decreases number of garbage collections of the blackboard artifacts and attributes objects (the objects are expected to be reused by the data event listeners).
|
* Passing the data as part of the event reduces memory footprint and decreases number of garbage collections of the blackboard artifacts and attributes objects (the objects are expected to be reused by the data event listeners).
|
||||||
*
|
*
|
||||||
* If a service does not pass the data as part of ServiceDataEvent (ServiceDataEvent.getArtifacts() returns null) - it is an indication that the service
|
* If a module does not pass the data as part of ModuleDataEvent (ModuleDataEvent.getArtifacts() returns null) - it is an indication that the module
|
||||||
* has new data but it does not implement new data tracking. The listener can then perform a blackboard query to get the latest data of interest (e.g. by artifact type).
|
* has new data but it does not implement new data tracking. The listener can then perform a blackboard query to get the latest data of interest (e.g. by artifact type).
|
||||||
*
|
*
|
||||||
* By design, only a single type of artifacts can be contained in a single data event.
|
* By design, only a single type of artifacts can be contained in a single data event.
|
||||||
*/
|
*/
|
||||||
public class ServiceDataEvent {
|
public class ModuleDataEvent {
|
||||||
|
|
||||||
private String serviceName;
|
private String moduleName;
|
||||||
private ARTIFACT_TYPE artifactType;
|
private ARTIFACT_TYPE artifactType;
|
||||||
private Collection<BlackboardArtifact> artifactIDs;
|
private Collection<BlackboardArtifact> artifactIDs;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param serviceName Module name
|
* @param moduleName Module name
|
||||||
* @param artifactType Type of artifact that was posted to blackboard
|
* @param artifactType Type of artifact that was posted to blackboard
|
||||||
*/
|
*/
|
||||||
public ServiceDataEvent(String serviceName, ARTIFACT_TYPE artifactType) {
|
public ModuleDataEvent(String moduleName, ARTIFACT_TYPE artifactType) {
|
||||||
this.serviceName = serviceName;
|
this.moduleName = moduleName;
|
||||||
this.artifactType = artifactType;
|
this.artifactType = artifactType;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param serviceName Module name
|
* @param moduleName Module name
|
||||||
* @param artifactType Type of artifact that was posted to blackboard
|
* @param artifactType Type of artifact that was posted to blackboard
|
||||||
* @param artifactIDs List of specific artifact ID values that were added to blackboard
|
* @param artifactIDs List of specific artifact ID values that were added to blackboard
|
||||||
*/
|
*/
|
||||||
public ServiceDataEvent(String serviceName, ARTIFACT_TYPE artifactType, Collection<BlackboardArtifact> artifactIDs) {
|
public ModuleDataEvent(String moduleName, ARTIFACT_TYPE artifactType, Collection<BlackboardArtifact> artifactIDs) {
|
||||||
this(serviceName, artifactType);
|
this(moduleName, artifactType);
|
||||||
this.artifactIDs = artifactIDs;
|
this.artifactIDs = artifactIDs;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -79,11 +79,11 @@ public class ServiceDataEvent {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* get service name that created the artifacts and fired the event
|
* get module name that created the artifacts and fired the event
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
public String getServiceName() {
|
public String getModuleName() {
|
||||||
return serviceName;
|
return moduleName;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -18,45 +18,45 @@
|
|||||||
*/
|
*/
|
||||||
package org.sleuthkit.autopsy.ingest.example;
|
package org.sleuthkit.autopsy.ingest.example;
|
||||||
|
|
||||||
import java.beans.PropertyChangeListener;
|
|
||||||
import java.util.logging.Level;
|
import java.util.logging.Level;
|
||||||
import java.util.logging.Logger;
|
import java.util.logging.Logger;
|
||||||
import org.sleuthkit.autopsy.ingest.IngestManagerProxy;
|
import org.sleuthkit.autopsy.ingest.IngestServices;
|
||||||
import org.sleuthkit.autopsy.ingest.IngestMessage;
|
import org.sleuthkit.autopsy.ingest.IngestMessage;
|
||||||
import org.sleuthkit.autopsy.ingest.IngestMessage.MessageType;
|
import org.sleuthkit.autopsy.ingest.IngestMessage.MessageType;
|
||||||
import org.sleuthkit.autopsy.ingest.IngestServiceAbstract.ServiceType;
|
import org.sleuthkit.autopsy.ingest.IngestModuleAbstract.ModuleType;
|
||||||
import org.sleuthkit.autopsy.ingest.IngestServiceAbstractFile;
|
import org.sleuthkit.autopsy.ingest.IngestModuleAbstractFile;
|
||||||
|
import org.sleuthkit.autopsy.ingest.IngestModuleInit;
|
||||||
import org.sleuthkit.datamodel.AbstractFile;
|
import org.sleuthkit.datamodel.AbstractFile;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Example implementation of a fscontent image ingest service
|
* Example implementation of a file ingest module
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
public class ExampleAbstractFileIngestService implements IngestServiceAbstractFile {
|
public class ExampleAbstractFileIngestModule implements IngestModuleAbstractFile {
|
||||||
|
|
||||||
private static final Logger logger = Logger.getLogger(ExampleAbstractFileIngestService.class.getName());
|
private static final Logger logger = Logger.getLogger(ExampleAbstractFileIngestModule.class.getName());
|
||||||
private static ExampleAbstractFileIngestService instance = null;
|
private static ExampleAbstractFileIngestModule instance = null;
|
||||||
private IngestManagerProxy managerProxy;
|
private IngestServices services;
|
||||||
private static int messageId = 0;
|
private static int messageId = 0;
|
||||||
|
|
||||||
//file ingest services require a private constructor
|
//file ingest modules require a private constructor
|
||||||
//to ensure singleton instances
|
//to ensure singleton instances
|
||||||
private ExampleAbstractFileIngestService() {
|
private ExampleAbstractFileIngestModule() {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static synchronized ExampleAbstractFileIngestService getDefault() {
|
public static synchronized ExampleAbstractFileIngestModule getDefault() {
|
||||||
if (instance == null) {
|
if (instance == null) {
|
||||||
instance = new ExampleAbstractFileIngestService();
|
instance = new ExampleAbstractFileIngestModule();
|
||||||
}
|
}
|
||||||
return instance;
|
return instance;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ProcessResult process(AbstractFile fsContent) {
|
public ProcessResult process(AbstractFile fsContent) {
|
||||||
managerProxy.postMessage(IngestMessage.createMessage(++messageId, MessageType.INFO, this, "Processing " + fsContent.getName()));
|
services.postMessage(IngestMessage.createMessage(++messageId, MessageType.INFO, this, "Processing " + fsContent.getName()));
|
||||||
|
|
||||||
//service specific AbstractFile processing code here
|
//module specific AbstractFile processing code here
|
||||||
try {
|
try {
|
||||||
Thread.sleep(100);
|
Thread.sleep(100);
|
||||||
} catch (InterruptedException e) {
|
} catch (InterruptedException e) {
|
||||||
@ -68,42 +68,42 @@ public class ExampleAbstractFileIngestService implements IngestServiceAbstractFi
|
|||||||
@Override
|
@Override
|
||||||
public void complete() {
|
public void complete() {
|
||||||
logger.log(Level.INFO, "complete()");
|
logger.log(Level.INFO, "complete()");
|
||||||
managerProxy.postMessage(IngestMessage.createMessage(++messageId, MessageType.INFO, this, "Complete"));
|
services.postMessage(IngestMessage.createMessage(++messageId, MessageType.INFO, this, "Complete"));
|
||||||
|
|
||||||
//service specific cleanup due completion here
|
//module specific cleanup due completion here
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getName() {
|
public String getName() {
|
||||||
return "Example AbstractFile Service";
|
return "Example AbstractFile Module";
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getDescription() {
|
public String getDescription() {
|
||||||
return "Example AbstractFile Service description";
|
return "Example AbstractFile Module description";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void init(IngestManagerProxy managerProxy) {
|
public void init(IngestModuleInit initContext) {
|
||||||
logger.log(Level.INFO, "init()");
|
logger.log(Level.INFO, "init()");
|
||||||
this.managerProxy = managerProxy;
|
services = IngestServices.getDefault();
|
||||||
|
|
||||||
//service specific initialization here
|
//module specific initialization here
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void stop() {
|
public void stop() {
|
||||||
logger.log(Level.INFO, "stop()");
|
logger.log(Level.INFO, "stop()");
|
||||||
managerProxy.postMessage(IngestMessage.createMessage(++messageId, MessageType.INFO, this, "Stopped"));
|
services.postMessage(IngestMessage.createMessage(++messageId, MessageType.INFO, this, "Stopped"));
|
||||||
|
|
||||||
//service specific cleanup due interruption here
|
//module specific cleanup due interruption here
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ServiceType getType() {
|
public ModuleType getType() {
|
||||||
return ServiceType.AbstractFile;
|
return ModuleType.AbstractFile;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
@ -18,36 +18,36 @@
|
|||||||
*/
|
*/
|
||||||
package org.sleuthkit.autopsy.ingest.example;
|
package org.sleuthkit.autopsy.ingest.example;
|
||||||
|
|
||||||
import java.beans.PropertyChangeListener;
|
|
||||||
import java.util.logging.Level;
|
import java.util.logging.Level;
|
||||||
import java.util.logging.Logger;
|
import java.util.logging.Logger;
|
||||||
import org.sleuthkit.autopsy.ingest.IngestImageWorkerController;
|
import org.sleuthkit.autopsy.ingest.IngestImageWorkerController;
|
||||||
import org.sleuthkit.autopsy.ingest.IngestManagerProxy;
|
import org.sleuthkit.autopsy.ingest.IngestServices;
|
||||||
import org.sleuthkit.autopsy.ingest.IngestMessage;
|
import org.sleuthkit.autopsy.ingest.IngestMessage;
|
||||||
import org.sleuthkit.autopsy.ingest.IngestMessage.MessageType;
|
import org.sleuthkit.autopsy.ingest.IngestMessage.MessageType;
|
||||||
import org.sleuthkit.autopsy.ingest.IngestServiceImage;
|
import org.sleuthkit.autopsy.ingest.IngestModuleImage;
|
||||||
|
import org.sleuthkit.autopsy.ingest.IngestModuleInit;
|
||||||
import org.sleuthkit.datamodel.Image;
|
import org.sleuthkit.datamodel.Image;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Example implementation of an image ingest service
|
* Example implementation of an image ingest service
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
public final class ExampleImageIngestService implements IngestServiceImage {
|
public final class ExampleImageIngestModule implements IngestModuleImage {
|
||||||
|
|
||||||
private static final Logger logger = Logger.getLogger(ExampleImageIngestService.class.getName());
|
private static final Logger logger = Logger.getLogger(ExampleImageIngestModule.class.getName());
|
||||||
private static ExampleImageIngestService defaultInstance = null;
|
private static ExampleImageIngestModule defaultInstance = null;
|
||||||
private IngestManagerProxy managerProxy;
|
private IngestServices services;
|
||||||
private static int messageId = 0;
|
private static int messageId = 0;
|
||||||
|
|
||||||
//public constructor is required
|
//public constructor is required
|
||||||
//as multiple instances are created for processing multiple images simultenously
|
//as multiple instances are created for processing multiple images simultenously
|
||||||
public ExampleImageIngestService() {
|
public ExampleImageIngestModule() {
|
||||||
}
|
}
|
||||||
|
|
||||||
//default instance used for service registration
|
//default instance used for service registration
|
||||||
public static synchronized ExampleImageIngestService getDefault() {
|
public static synchronized ExampleImageIngestModule getDefault() {
|
||||||
if (defaultInstance == null) {
|
if (defaultInstance == null) {
|
||||||
defaultInstance = new ExampleImageIngestService();
|
defaultInstance = new ExampleImageIngestModule();
|
||||||
}
|
}
|
||||||
return defaultInstance;
|
return defaultInstance;
|
||||||
}
|
}
|
||||||
@ -56,7 +56,7 @@ public final class ExampleImageIngestService implements IngestServiceImage {
|
|||||||
public void process(Image image, IngestImageWorkerController controller) {
|
public void process(Image image, IngestImageWorkerController controller) {
|
||||||
logger.log(Level.INFO, "process() " + this.toString());
|
logger.log(Level.INFO, "process() " + this.toString());
|
||||||
|
|
||||||
managerProxy.postMessage(IngestMessage.createMessage(++messageId, MessageType.INFO, this, "Processing " + image.getName()));
|
services.postMessage(IngestMessage.createMessage(++messageId, MessageType.INFO, this, "Processing " + image.getName()));
|
||||||
|
|
||||||
//service specific Image processing code here
|
//service specific Image processing code here
|
||||||
//example:
|
//example:
|
||||||
@ -76,7 +76,7 @@ public final class ExampleImageIngestService implements IngestServiceImage {
|
|||||||
//do the work
|
//do the work
|
||||||
Thread.sleep(500);
|
Thread.sleep(500);
|
||||||
//post message to user if found something interesting
|
//post message to user if found something interesting
|
||||||
managerProxy.postMessage(IngestMessage.createMessage(processedFiles, MessageType.INFO, this, "Processed " + image.getName() + ": " + Integer.toString(processedFiles)));
|
services.postMessage(IngestMessage.createMessage(processedFiles, MessageType.INFO, this, "Processed " + image.getName() + ": " + Integer.toString(processedFiles)));
|
||||||
|
|
||||||
//update progress
|
//update progress
|
||||||
controller.progress(++processedFiles);
|
controller.progress(++processedFiles);
|
||||||
@ -92,7 +92,7 @@ public final class ExampleImageIngestService implements IngestServiceImage {
|
|||||||
logger.log(Level.INFO, "complete() " + this.toString());
|
logger.log(Level.INFO, "complete() " + this.toString());
|
||||||
|
|
||||||
final IngestMessage msg = IngestMessage.createMessage(++messageId, MessageType.INFO, this, "Complete");
|
final IngestMessage msg = IngestMessage.createMessage(++messageId, MessageType.INFO, this, "Complete");
|
||||||
managerProxy.postMessage(msg);
|
services.postMessage(msg);
|
||||||
|
|
||||||
//service specific cleanup due to completion here
|
//service specific cleanup due to completion here
|
||||||
}
|
}
|
||||||
@ -108,9 +108,9 @@ public final class ExampleImageIngestService implements IngestServiceImage {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void init(IngestManagerProxy managerProxy) {
|
public void init(IngestModuleInit initContext) {
|
||||||
logger.log(Level.INFO, "init() " + this.toString());
|
logger.log(Level.INFO, "init() " + this.toString());
|
||||||
this.managerProxy = managerProxy;
|
services = IngestServices.getDefault();
|
||||||
|
|
||||||
//service specific initialization here
|
//service specific initialization here
|
||||||
|
|
||||||
@ -119,14 +119,14 @@ public final class ExampleImageIngestService implements IngestServiceImage {
|
|||||||
@Override
|
@Override
|
||||||
public void stop() {
|
public void stop() {
|
||||||
logger.log(Level.INFO, "stop()");
|
logger.log(Level.INFO, "stop()");
|
||||||
managerProxy.postMessage(IngestMessage.createMessage(++messageId, MessageType.INFO, this, "Stopped"));
|
services.postMessage(IngestMessage.createMessage(++messageId, MessageType.INFO, this, "Stopped"));
|
||||||
|
|
||||||
//service specific cleanup due to interruption here
|
//service specific cleanup due to interruption here
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ServiceType getType() {
|
public ModuleType getType() {
|
||||||
return ServiceType.Image;
|
return ModuleType.Image;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
@ -14,17 +14,17 @@
|
|||||||
<attr name="instanceCreate" methodvalue="org.sleuthkit.autopsy.ingest.IngestMessageTopComponent.findInstance"/>
|
<attr name="instanceCreate" methodvalue="org.sleuthkit.autopsy.ingest.IngestMessageTopComponent.findInstance"/>
|
||||||
<attr name="position" intvalue="100"/>
|
<attr name="position" intvalue="100"/>
|
||||||
</file> -->
|
</file> -->
|
||||||
<!-- example services -->
|
<!-- example modules -->
|
||||||
<!--
|
<!--
|
||||||
<file name="org-sleuthkit-autopsy-ingest-example-ExampleImageIngestService.instance">
|
<file name="org-sleuthkit-autopsy-ingest-example-ExampleImageIngestModule.instance">
|
||||||
<attr name="instanceOf" stringvalue="org.sleuthkit.autopsy.ingest.IngestServiceImage"/>
|
<attr name="instanceOf" stringvalue="org.sleuthkit.autopsy.ingest.IngestModuleImage"/>
|
||||||
<attr name="instanceCreate" methodvalue="org.sleuthkit.autopsy.ingest.example.ExampleImageIngestService.getDefault"/>
|
<attr name="instanceCreate" methodvalue="org.sleuthkit.autopsy.ingest.example.ExampleImageIngestModule.getDefault"/>
|
||||||
<attr name="position" intvalue="1000"/>
|
<attr name="position" intvalue="1000"/>
|
||||||
</file>
|
</file>
|
||||||
|
|
||||||
<file name="org-sleuthkit-autopsy-ingest-example-ExampleAbstractFileIngestService.instance">
|
<file name="org-sleuthkit-autopsy-ingest-example-ExampleAbstractFileIngestModule.instance">
|
||||||
<attr name="instanceOf" stringvalue="org.sleuthkit.autopsy.ingest.IngestServiceAbstractFile"/>
|
<attr name="instanceOf" stringvalue="org.sleuthkit.autopsy.ingest.IngestModuleAbstractFile"/>
|
||||||
<attr name="instanceCreate" methodvalue="org.sleuthkit.autopsy.ingest.example.ExampleAbstractFileIngestService.getDefault"/>
|
<attr name="instanceCreate" methodvalue="org.sleuthkit.autopsy.ingest.example.ExampleAbstractFileIngestModule.getDefault"/>
|
||||||
<attr name="position" intvalue="1100"/>
|
<attr name="position" intvalue="1100"/>
|
||||||
</file>
|
</file>
|
||||||
-->
|
-->
|
||||||
|
@ -5,7 +5,7 @@
|
|||||||
|
|
||||||
The package provides the ingest module framework. Ingest modules perform data analysis in a multi-threaded approach.
|
The package provides the ingest module framework. Ingest modules perform data analysis in a multi-threaded approach.
|
||||||
|
|
||||||
\section ingestmodue_contents Package Contents
|
\section ingestmodule_contents Package Contents
|
||||||
|
|
||||||
The following are important classes in this package:
|
The following are important classes in this package:
|
||||||
- IngestManager
|
- IngestManager
|
||||||
@ -31,17 +31,17 @@ Refer to org.sleuthkit.autopsy.ingest.example for sample source code.
|
|||||||
|
|
||||||
\subsection ingestmodule_making_api Module Interface
|
\subsection ingestmodule_making_api Module Interface
|
||||||
|
|
||||||
The first step is to choose the correct module type. Image-level modules will implement the IngestServiceImage interface and file-level modules will implement the IngestServiceAbstractFile interface.
|
The first step is to choose the correct module type. Image-level modules will implement the IngestModuleImage interface and file-level modules will implement the IngestModuleAbstractFile interface.
|
||||||
|
|
||||||
There is a static getDefault() method that is not part of the interface, that every module (whether an image or a file service) needs to implement to return the registered static instance of the service. Refer to example code in example.ExampleAbstractFileIngestService.getDefault()
|
There is a static getDefault() method that is not part of the interface, that every module (whether an image or a file module) needs to implement to return the registered static instance of the module. Refer to example code in example.ExampleAbstractFileIngestModule.getDefault()
|
||||||
|
|
||||||
File-level modules need to be singleton (only a single instance at a time). To ensure this, make the constructor private. Ensure the default public file service constructor is overridden with the private one. Image-level modules require a public constructor.
|
File-level modules need to be singleton (only a single instance at a time). To ensure this, make the constructor private. Ensure the default public file module constructor is overridden with the private one. Image-level modules require a public constructor.
|
||||||
|
|
||||||
The interfaces have several standard methods that need to be implemented. See the interface methods for details.
|
The interfaces have several standard methods that need to be implemented. See the interface methods for details.
|
||||||
- IngestServiceAbstract.init() is invoked every time an ingest session starts. A module should support multiple invocations of init() throughout the application life-cycle.
|
- IngestModuleAbstract.init() is invoked every time an ingest session starts. A module should support multiple invocations of init() throughout the application life-cycle.
|
||||||
- IngestServiceAbstract.complete() is invoked when an ingest session completes. The module should perform any resource (files, handles, caches) cleanup in this method and submit final results and post a final ingest inbox message.
|
- IngestModuleAbstract.complete() is invoked when an ingest session completes. The module should perform any resource (files, handles, caches) cleanup in this method and submit final results and post a final ingest inbox message.
|
||||||
- IngestServiceAbstract.stop() is invoked on a module when an ingest session is interrupted by the user or by the system.
|
- IngestModuleAbstract.stop() is invoked on a module when an ingest session is interrupted by the user or by the system.
|
||||||
The method implementation should be similar to complete() in that the service should perform any cleanup work. If there is pending data to be processed or pending results to be reported by the service then the results should be rejected and ignored if stop() is invoked and the module should terminate as early as possible.
|
The method implementation should be similar to complete() in that the module should perform any cleanup work. If there is pending data to be processed or pending results to be reported by the module then the results should be rejected and ignored if stop() is invoked and the module should terminate as early as possible.
|
||||||
- process() method is invoked to analyze the data. The specific method depends on the module type.
|
- process() method is invoked to analyze the data. The specific method depends on the module type.
|
||||||
|
|
||||||
|
|
||||||
@ -55,7 +55,7 @@ Module developers are encouraged to use the standard java.util.logging.Logger in
|
|||||||
|
|
||||||
\subsection ingestmodule_making_process Process Method
|
\subsection ingestmodule_making_process Process Method
|
||||||
The process method is where the work is done in each type of module. Some notes:
|
The process method is where the work is done in each type of module. Some notes:
|
||||||
- File-level modules will be called on each file in an order determined by the IngestManager. Each module is free to quickly ignore a file based on name, signature, etc. If a module wants to know the return value from a previously run module, it should use the IngestManagerProxy.getAbstractFileServiceResult() method.
|
- File-level modules will be called on each file in an order determined by the IngestManager. Each module is free to quickly ignore a file based on name, signature, etc. If a module wants to know the return value from a previously run module, it should use the IngestServices.getAbstractFileModuleResult() method.
|
||||||
- Image-level modules are expected not passed in specific files and are expected to query the database to find the files that they are interested in.
|
- Image-level modules are expected not passed in specific files and are expected to query the database to find the files that they are interested in.
|
||||||
|
|
||||||
|
|
||||||
@ -65,9 +65,9 @@ Ingest modules need to be registered using the Netbeans Lookup infrastructure in
|
|||||||
|
|
||||||
An example Image-level module is:
|
An example Image-level module is:
|
||||||
\verbatim
|
\verbatim
|
||||||
<file name="org-sleuthkit-autopsy-ingest-example-ExampleImageIngestService.instance">
|
<file name="org-sleuthkit-autopsy-ingest-example-ExampleImageIngestModule.instance">
|
||||||
<attr name="instanceOf" stringvalue="org.sleuthkit.autopsy.ingest.IngestServiceImage"/>
|
<attr name="instanceOf" stringvalue="org.sleuthkit.autopsy.ingest.IngestModuleImage"/>
|
||||||
<attr name="instanceCreate" methodvalue="org.sleuthkit.autopsy.ingest.example.ExampleImageIngestService.getDefault"/>
|
<attr name="instanceCreate" methodvalue="org.sleuthkit.autopsy.ingest.example.ExampleImageIngestModule.getDefault"/>
|
||||||
<attr name="position" intvalue="1000"/>
|
<attr name="position" intvalue="1000"/>
|
||||||
</file>
|
</file>
|
||||||
\endverbatim
|
\endverbatim
|
||||||
@ -75,16 +75,16 @@ An example Image-level module is:
|
|||||||
An example file-level module is:
|
An example file-level module is:
|
||||||
|
|
||||||
\verbatim
|
\verbatim
|
||||||
<file name="org-sleuthkit-autopsy-ingest-example-ExampleAbstractFileIngestService.instance">
|
<file name="org-sleuthkit-autopsy-ingest-example-ExampleAbstractFileIngestModule.instance">
|
||||||
<attr name="instanceOf" stringvalue="org.sleuthkit.autopsy.ingest.IngestServiceAbstractFile"/>
|
<attr name="instanceOf" stringvalue="org.sleuthkit.autopsy.ingest.IngestModuleAbstractFile"/>
|
||||||
<attr name="instanceCreate" methodvalue="org.sleuthkit.autopsy.ingest.example.ExampleAbstractFileIngestService.getDefault"/>
|
<attr name="instanceCreate" methodvalue="org.sleuthkit.autopsy.ingest.example.ExampleAbstractFileIngestModule.getDefault"/>
|
||||||
<attr name="position" intvalue="1100"/>
|
<attr name="position" intvalue="1100"/>
|
||||||
</file>
|
</file>
|
||||||
\endverbatim
|
\endverbatim
|
||||||
|
|
||||||
Note the "position" attribute. The attribute determines the ordering of the module in the ingest pipeline.
|
Note the "position" attribute. The attribute determines the ordering of the module in the ingest pipeline.
|
||||||
Services with lower position attribute will execute earlier.
|
Modules with lower position attribute will execute earlier.
|
||||||
Use high numbers (higher than 1000) for non-core services. If your module depends on results from another module, use a higher position attribute to enforce the dependency.
|
Use high numbers (higher than 1000) for non-core modules. If your module depends on results from another module, use a higher position attribute to enforce the dependency.
|
||||||
|
|
||||||
Note: we plan to implement a more flexible and robust module dependency system in future versions of the Autopsy ingest framework.
|
Note: we plan to implement a more flexible and robust module dependency system in future versions of the Autopsy ingest framework.
|
||||||
|
|
||||||
@ -97,11 +97,11 @@ Users will see the results from ingest modules in one of two ways:
|
|||||||
- Results are posted to the blackboard and will be displayed in the navigation tree
|
- Results are posted to the blackboard and will be displayed in the navigation tree
|
||||||
- Messages are sent to the Ingest Inbox to notify a user of what has recently been found.
|
- Messages are sent to the Ingest Inbox to notify a user of what has recently been found.
|
||||||
|
|
||||||
See the Blackboard (REFERENCE) documentation for posting results to it. Modules are free to immediately post results when they find them or they can wait. The IngestManagerProxy.getUpdateFrequency() method returns the maximum amount of time that a module can wait before it posts its results.
|
See the Blackboard (REFERENCE) documentation for posting results to it. Modules are free to immediately post results when they find them or they can wait. The IngestServices.getUpdateFrequency() method returns the maximum amount of time that a module can wait before it posts its results.
|
||||||
|
|
||||||
An example of waiting to post results is the keyword search module. It is resource intensive to commit the keyword index and do a keyword search. Therefore, when its process() method is invoked, it checks if it is close to the getUpdateFrequency() since the last time it did a keyword search. If it is, then it commits the index and performs the search.
|
An example of waiting to post results is the keyword search module. It is resource intensive to commit the keyword index and do a keyword search. Therefore, when its process() method is invoked, it checks if it is close to the getUpdateFrequency() since the last time it did a keyword search. If it is, then it commits the index and performs the search.
|
||||||
|
|
||||||
When they add data to the blackboard, modules should notify listeners of the new data by periodically invoking IngestManagerProxy.fireServiceDataEvent() method. This allows other modules (and the main UI) to know when to query the blackboard for the latest data.
|
When they add data to the blackboard, modules should notify listeners of the new data by periodically invoking IngestServices.fireModuleDataEvent() method. This allows other modules (and the main UI) to know when to query the blackboard for the latest data.
|
||||||
|
|
||||||
Modules should post messages to the inbox when interesting data is found. The messages includes the module name, message subject, message details, a unique message id (in the context of the originating module), and a uniqueness attribute. The uniqueness attribute is used to group similar messages together and to determine the overall importance priority of the message (if the same message is seen repeatedly, it is considered lower priority).
|
Modules should post messages to the inbox when interesting data is found. The messages includes the module name, message subject, message details, a unique message id (in the context of the originating module), and a uniqueness attribute. The uniqueness attribute is used to group similar messages together and to determine the overall importance priority of the message (if the same message is seen repeatedly, it is considered lower priority).
|
||||||
|
|
||||||
@ -111,7 +111,7 @@ Ingest messages have different types: there are info messages, warning messages,
|
|||||||
The data messages contain encapsulated blackboard artifacts and attributes. The passed in data is used by the ingest inbox GUI widget to navigate to the artifact view in the directory tree, if requested by the user.
|
The data messages contain encapsulated blackboard artifacts and attributes. The passed in data is used by the ingest inbox GUI widget to navigate to the artifact view in the directory tree, if requested by the user.
|
||||||
|
|
||||||
Ingest message API is defined in IngestMessage class. The class also contains factory methods to create new messages.
|
Ingest message API is defined in IngestMessage class. The class also contains factory methods to create new messages.
|
||||||
Messages are posted using IngestManagerProxy.postMessage() method, which accepts a message object created using one of the factory methods.
|
Messages are posted using IngestServices.postMessage() method, which accepts a message object created using one of the factory methods.
|
||||||
|
|
||||||
Modules should post inbox messages to the user when stop() or complete() is invoked (refer to the examples).
|
Modules should post inbox messages to the user when stop() or complete() is invoked (refer to the examples).
|
||||||
It is recommended to populate the description field of the complete inbox message to provide feedback to the user
|
It is recommended to populate the description field of the complete inbox message to provide feedback to the user
|
||||||
@ -134,13 +134,13 @@ Module configuration is decentralized and module-specific; every module maintain
|
|||||||
own configuration state and is responsible for implementing the graphical interface.
|
own configuration state and is responsible for implementing the graphical interface.
|
||||||
|
|
||||||
The run-time configuration (also called simple configuration), is achieved by each
|
The run-time configuration (also called simple configuration), is achieved by each
|
||||||
ingest module providing a JPanel. The IngestServiceAbstract.hasSimpleConfiguration(),
|
ingest module providing a JPanel. The IngestModuleAbstract.hasSimpleConfiguration(),
|
||||||
IngestServiceAbstract.getSimpleConfiguration(), and IngestServiceAbstract.saveSimpleConfiguration()
|
IngestModuleAbstract.getSimpleConfiguration(), and IngestModuleAbstract.saveSimpleConfiguration()
|
||||||
methods should be used for run-time configuration.
|
methods should be used for run-time configuration.
|
||||||
|
|
||||||
The general configuration is also achieved by the module returning a JPanel. A link will be provided to the general configuration from the ingest manager if it exists.
|
The general configuration is also achieved by the module returning a JPanel. A link will be provided to the general configuration from the ingest manager if it exists.
|
||||||
The IngestServiceAbstract.hasAdvancedConfiguration(),
|
The IngestModuleAbstract.hasAdvancedConfiguration(),
|
||||||
IngestServiceAbstract.getAdvancedConfiguration(), and IngestServiceAbstract.saveAdvancedConfiguration()
|
IngestModuleAbstract.getAdvancedConfiguration(), and IngestModuleAbstract.saveAdvancedConfiguration()
|
||||||
methods should be used for general configuration.
|
methods should be used for general configuration.
|
||||||
|
|
||||||
|
|
||||||
@ -152,14 +152,14 @@ methods should be used for general configuration.
|
|||||||
Other modules and core Autopsy classes may want to get the status of the ingest manager. The IngestManager provides access to this data with the sleuthkit.autopsy.ingest.IngestManager.isIngestRunning() method.
|
Other modules and core Autopsy classes may want to get the status of the ingest manager. The IngestManager provides access to this data with the sleuthkit.autopsy.ingest.IngestManager.isIngestRunning() method.
|
||||||
|
|
||||||
|
|
||||||
External modules can also register themselves as ingest service event listeners and receive event notifications (when a module is started, stopped, completed or has new data).
|
External modules can also register themselves as ingest module event listeners and receive event notifications (when a module is started, stopped, completed or has new data).
|
||||||
Use the IngestManager.addPropertyChangeListener() method to register a service event listener.
|
Use the IngestManager.addPropertyChangeListener() method to register a module event listener.
|
||||||
Events types received are defined in IngestManager.IngestModuleEvent enum.
|
Events types received are defined in IngestManager.IngestModuleEvent enum.
|
||||||
|
|
||||||
At the end of the ingest, IngestManager itself will notify all listeners of IngestModuleEvent.COMPLETED event.
|
At the end of the ingest, IngestManager itself will notify all listeners of IngestModuleEvent.COMPLETED event.
|
||||||
The event is an indication for listeners to perform the final data refresh by quering the blackboard.
|
The event is an indication for listeners to perform the final data refresh by quering the blackboard.
|
||||||
Module developers are encouraged to generate periodic IngestModuleEvent.DATA
|
Module developers are encouraged to generate periodic IngestModuleEvent.DATA
|
||||||
ServiceDataEvent events when they post data to the blackboard,
|
ModuleDataEvent events when they post data to the blackboard,
|
||||||
but the IngestManager will make a final event to handle scenarios where the module did not notify listeners while it was running.
|
but the IngestManager will make a final event to handle scenarios where the module did not notify listeners while it was running.
|
||||||
|
|
||||||
*/
|
*/
|
||||||
|
@ -43,7 +43,7 @@ public class AbstractFileHtmlExtract implements AbstractFileExtract {
|
|||||||
private static final int SINGLE_READ_CHARS = 1024;
|
private static final int SINGLE_READ_CHARS = 1024;
|
||||||
private static final int EXTRA_CHARS = 128; //for whitespace
|
private static final int EXTRA_CHARS = 128; //for whitespace
|
||||||
private static final char[] TEXT_CHUNK_BUF = new char[MAX_EXTR_TEXT_CHARS];
|
private static final char[] TEXT_CHUNK_BUF = new char[MAX_EXTR_TEXT_CHARS];
|
||||||
private KeywordSearchIngestService service;
|
private KeywordSearchIngestModule module;
|
||||||
private Ingester ingester;
|
private Ingester ingester;
|
||||||
private AbstractFile sourceFile;
|
private AbstractFile sourceFile;
|
||||||
private int numChunks = 0;
|
private int numChunks = 0;
|
||||||
@ -53,7 +53,7 @@ public class AbstractFileHtmlExtract implements AbstractFileExtract {
|
|||||||
};
|
};
|
||||||
|
|
||||||
AbstractFileHtmlExtract() {
|
AbstractFileHtmlExtract() {
|
||||||
this.service = KeywordSearchIngestService.getDefault();
|
this.module = KeywordSearchIngestModule.getDefault();
|
||||||
ingester = Server.getIngester();
|
ingester = Server.getIngester();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -161,7 +161,7 @@ public class AbstractFileHtmlExtract implements AbstractFileExtract {
|
|||||||
|
|
||||||
//check if need invoke commit/search between chunks
|
//check if need invoke commit/search between chunks
|
||||||
//not to delay commit if timer has gone off
|
//not to delay commit if timer has gone off
|
||||||
service.checkRunCommitSearch();
|
module.checkRunCommitSearch();
|
||||||
}
|
}
|
||||||
} catch (IOException ex) {
|
} catch (IOException ex) {
|
||||||
logger.log(Level.WARNING, "Unable to read content stream from " + sourceFile.getId() + ": " + sourceFile.getName(), ex);
|
logger.log(Level.WARNING, "Unable to read content stream from " + sourceFile.getId() + ": " + sourceFile.getName(), ex);
|
||||||
|
@ -39,7 +39,7 @@ import org.sleuthkit.datamodel.AbstractFile;
|
|||||||
*/
|
*/
|
||||||
class AbstractFileStringExtract implements AbstractFileExtract {
|
class AbstractFileStringExtract implements AbstractFileExtract {
|
||||||
|
|
||||||
private KeywordSearchIngestService service;
|
private KeywordSearchIngestModule module;
|
||||||
private Ingester ingester;
|
private Ingester ingester;
|
||||||
private int numChunks;
|
private int numChunks;
|
||||||
private static final Logger logger = Logger.getLogger(AbstractFileStringExtract.class.getName());
|
private static final Logger logger = Logger.getLogger(AbstractFileStringExtract.class.getName());
|
||||||
@ -61,7 +61,7 @@ class AbstractFileStringExtract implements AbstractFileExtract {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public AbstractFileStringExtract() {
|
public AbstractFileStringExtract() {
|
||||||
this.service = KeywordSearchIngestService.getDefault();
|
this.module = KeywordSearchIngestModule.getDefault();
|
||||||
this.ingester = Server.getIngester();
|
this.ingester = Server.getIngester();
|
||||||
this.extractScripts.add(DEFAULT_SCRIPT);
|
this.extractScripts.add(DEFAULT_SCRIPT);
|
||||||
}
|
}
|
||||||
@ -122,7 +122,7 @@ class AbstractFileStringExtract implements AbstractFileExtract {
|
|||||||
|
|
||||||
//check if need invoke commit/search between chunks
|
//check if need invoke commit/search between chunks
|
||||||
//not to delay commit if timer has gone off
|
//not to delay commit if timer has gone off
|
||||||
service.checkRunCommitSearch();
|
module.checkRunCommitSearch();
|
||||||
|
|
||||||
//debug.close();
|
//debug.close();
|
||||||
}
|
}
|
||||||
|
@ -32,7 +32,7 @@ import java.util.concurrent.TimeUnit;
|
|||||||
import java.util.concurrent.TimeoutException;
|
import java.util.concurrent.TimeoutException;
|
||||||
import java.util.logging.Level;
|
import java.util.logging.Level;
|
||||||
import java.util.logging.Logger;
|
import java.util.logging.Logger;
|
||||||
import org.sleuthkit.autopsy.ingest.IngestServiceAbstractFile;
|
import org.sleuthkit.autopsy.ingest.IngestModuleAbstractFile;
|
||||||
import org.sleuthkit.datamodel.AbstractFile;
|
import org.sleuthkit.datamodel.AbstractFile;
|
||||||
import org.sleuthkit.datamodel.ReadContentInputStream;
|
import org.sleuthkit.datamodel.ReadContentInputStream;
|
||||||
import org.apache.tika.Tika;
|
import org.apache.tika.Tika;
|
||||||
@ -52,7 +52,7 @@ import org.sleuthkit.autopsy.keywordsearch.Ingester.IngesterException;
|
|||||||
*/
|
*/
|
||||||
public class AbstractFileTikaTextExtract implements AbstractFileExtract {
|
public class AbstractFileTikaTextExtract implements AbstractFileExtract {
|
||||||
|
|
||||||
private static final Logger logger = Logger.getLogger(IngestServiceAbstractFile.class.getName());
|
private static final Logger logger = Logger.getLogger(IngestModuleAbstractFile.class.getName());
|
||||||
private static final Logger tikaLogger = KeywordSearch.getTikaLogger();
|
private static final Logger tikaLogger = KeywordSearch.getTikaLogger();
|
||||||
private static final Charset OUTPUT_CHARSET = Server.DEFAULT_INDEXED_TEXT_CHARSET;
|
private static final Charset OUTPUT_CHARSET = Server.DEFAULT_INDEXED_TEXT_CHARSET;
|
||||||
static final int MAX_EXTR_TEXT_CHARS = 512 * 1024;
|
static final int MAX_EXTR_TEXT_CHARS = 512 * 1024;
|
||||||
@ -60,7 +60,7 @@ public class AbstractFileTikaTextExtract implements AbstractFileExtract {
|
|||||||
private static final int EXTRA_CHARS = 128; //for whitespace
|
private static final int EXTRA_CHARS = 128; //for whitespace
|
||||||
private static final char[] TEXT_CHUNK_BUF = new char[MAX_EXTR_TEXT_CHARS];
|
private static final char[] TEXT_CHUNK_BUF = new char[MAX_EXTR_TEXT_CHARS];
|
||||||
//private Tika tika;
|
//private Tika tika;
|
||||||
private KeywordSearchIngestService service;
|
private KeywordSearchIngestModule module;
|
||||||
private static Ingester ingester;
|
private static Ingester ingester;
|
||||||
private AbstractFile sourceFile; //currently processed file
|
private AbstractFile sourceFile; //currently processed file
|
||||||
private int numChunks = 0;
|
private int numChunks = 0;
|
||||||
@ -74,7 +74,7 @@ public class AbstractFileTikaTextExtract implements AbstractFileExtract {
|
|||||||
"pst", "xml", "class", "dwg", "eml", "emlx", "mbox", "mht"};
|
"pst", "xml", "class", "dwg", "eml", "emlx", "mbox", "mht"};
|
||||||
|
|
||||||
AbstractFileTikaTextExtract() {
|
AbstractFileTikaTextExtract() {
|
||||||
this.service = KeywordSearchIngestService.getDefault();
|
this.module = KeywordSearchIngestModule.getDefault();
|
||||||
ingester = Server.getIngester();
|
ingester = Server.getIngester();
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -216,7 +216,7 @@ public class AbstractFileTikaTextExtract implements AbstractFileExtract {
|
|||||||
|
|
||||||
//check if need invoke commit/search between chunks
|
//check if need invoke commit/search between chunks
|
||||||
//not to delay commit if timer has gone off
|
//not to delay commit if timer has gone off
|
||||||
service.checkRunCommitSearch();
|
module.checkRunCommitSearch();
|
||||||
}
|
}
|
||||||
} catch (IOException ex) {
|
} catch (IOException ex) {
|
||||||
final String msg = "Unable to read content stream from " + sourceFile.getId() + ": " + sourceFile.getName();
|
final String msg = "Unable to read content stream from " + sourceFile.getId() + ": " + sourceFile.getName();
|
||||||
|
@ -79,8 +79,8 @@ abstract class AbstractKeywordSearchPerformer extends javax.swing.JPanel impleme
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
//check if keyword search service ingest is running (indexing, etc)
|
//check if keyword search module ingest is running (indexing, etc)
|
||||||
if (IngestManager.getDefault().isServiceRunning(KeywordSearchIngestService.getDefault())) {
|
if (IngestManager.getDefault().isModuleRunning(KeywordSearchIngestModule.getDefault())) {
|
||||||
if (KeywordSearchUtil.displayConfirmDialog("Keyword Search Ingest in Progress",
|
if (KeywordSearchUtil.displayConfirmDialog("Keyword Search Ingest in Progress",
|
||||||
"<html>Keyword Search Ingest is currently running.<br />"
|
"<html>Keyword Search Ingest is currently running.<br />"
|
||||||
+ "Not all files have been indexed and this search might yield incomplete results.<br />"
|
+ "Not all files have been indexed and this search might yield incomplete results.<br />"
|
||||||
|
@ -31,6 +31,6 @@ public final class KeywordSearchAction extends AbstractAction implements Present
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Component getToolbarPresenter() {
|
public Component getToolbarPresenter() {
|
||||||
return new KeywordSearchPanel();
|
return KeywordSearchPanel.getDefault();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -59,10 +59,10 @@ public class KeywordSearchConfigurationPanel2 extends javax.swing.JPanel {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void activateWidgets() {
|
private void activateWidgets() {
|
||||||
final KeywordSearchIngestService service = KeywordSearchIngestService.getDefault();
|
final KeywordSearchIngestModule service = KeywordSearchIngestModule.getDefault();
|
||||||
skipNSRLCheckBox.setSelected(service.getSkipKnown());
|
skipNSRLCheckBox.setSelected(service.getSkipKnown());
|
||||||
boolean enable = !IngestManager.getDefault().isIngestRunning()
|
boolean enable = !IngestManager.getDefault().isIngestRunning()
|
||||||
&& ! IngestManager.getDefault().isServiceRunning(KeywordSearchIngestService.getDefault());
|
&& ! IngestManager.getDefault().isModuleRunning(KeywordSearchIngestModule.getDefault());
|
||||||
skipNSRLCheckBox.setEnabled(enable);
|
skipNSRLCheckBox.setEnabled(enable);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -139,7 +139,7 @@ public class KeywordSearchConfigurationPanel2 extends javax.swing.JPanel {
|
|||||||
}// </editor-fold>//GEN-END:initComponents
|
}// </editor-fold>//GEN-END:initComponents
|
||||||
|
|
||||||
private void skipNSRLCheckBoxActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_skipNSRLCheckBoxActionPerformed
|
private void skipNSRLCheckBoxActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_skipNSRLCheckBoxActionPerformed
|
||||||
KeywordSearchIngestService.getDefault().setSkipKnown(skipNSRLCheckBox.isSelected());
|
KeywordSearchIngestModule.getDefault().setSkipKnown(skipNSRLCheckBox.isSelected());
|
||||||
}//GEN-LAST:event_skipNSRLCheckBoxActionPerformed
|
}//GEN-LAST:event_skipNSRLCheckBoxActionPerformed
|
||||||
// Variables declaration - do not modify//GEN-BEGIN:variables
|
// Variables declaration - do not modify//GEN-BEGIN:variables
|
||||||
private javax.swing.JLabel chunksLabel;
|
private javax.swing.JLabel chunksLabel;
|
||||||
@ -152,7 +152,7 @@ private void skipNSRLCheckBoxActionPerformed(java.awt.event.ActionEvent evt) {//
|
|||||||
// End of variables declaration//GEN-END:variables
|
// End of variables declaration//GEN-END:variables
|
||||||
|
|
||||||
private void customizeComponents() {
|
private void customizeComponents() {
|
||||||
this.skipNSRLCheckBox.setSelected(KeywordSearchIngestService.getDefault().getSkipKnown());
|
this.skipNSRLCheckBox.setSelected(KeywordSearchIngestModule.getDefault().getSkipKnown());
|
||||||
|
|
||||||
try {
|
try {
|
||||||
filesIndexedValue.setText(Integer.toString(KeywordSearch.getServer().queryNumIndexedFiles()));
|
filesIndexedValue.setText(Integer.toString(KeywordSearch.getServer().queryNumIndexedFiles()));
|
||||||
|
@ -64,7 +64,7 @@ public class KeywordSearchConfigurationPanel3 extends javax.swing.JPanel {
|
|||||||
toUpdate.add(s);
|
toUpdate.add(s);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
KeywordSearchIngestService.getDefault().setStringExtractScripts(toUpdate);
|
KeywordSearchIngestModule.getDefault().setStringExtractScripts(toUpdate);
|
||||||
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@ -104,7 +104,7 @@ public class KeywordSearchConfigurationPanel3 extends javax.swing.JPanel {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void reloadScriptsCheckBoxes() {
|
private void reloadScriptsCheckBoxes() {
|
||||||
final KeywordSearchIngestService service = KeywordSearchIngestService.getDefault();
|
final KeywordSearchIngestModule service = KeywordSearchIngestModule.getDefault();
|
||||||
final List<SCRIPT> serviceScripts = service.getStringExtractScripts();
|
final List<SCRIPT> serviceScripts = service.getStringExtractScripts();
|
||||||
final int components = checkPanel.getComponentCount();
|
final int components = checkPanel.getComponentCount();
|
||||||
for (int i = 0; i < components; ++i) {
|
for (int i = 0; i < components; ++i) {
|
||||||
@ -118,7 +118,7 @@ public class KeywordSearchConfigurationPanel3 extends javax.swing.JPanel {
|
|||||||
private void activateWidgets() {
|
private void activateWidgets() {
|
||||||
reloadScriptsCheckBoxes();
|
reloadScriptsCheckBoxes();
|
||||||
boolean enable = !IngestManager.getDefault().isIngestRunning()
|
boolean enable = !IngestManager.getDefault().isIngestRunning()
|
||||||
&& ! IngestManager.getDefault().isServiceRunning(KeywordSearchIngestService.getDefault());;
|
&& ! IngestManager.getDefault().isModuleRunning(KeywordSearchIngestModule.getDefault());;
|
||||||
//enable / disable checboxes
|
//enable / disable checboxes
|
||||||
activateScriptsCheckboxes(enable);
|
activateScriptsCheckboxes(enable);
|
||||||
}
|
}
|
||||||
|
@ -178,7 +178,7 @@ class KeywordSearchEditListPanel extends javax.swing.JPanel implements ListSelec
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
if (IngestManager.getDefault().isServiceRunning(KeywordSearchIngestService.getDefault())) {
|
if (IngestManager.getDefault().isModuleRunning(KeywordSearchIngestModule.getDefault())) {
|
||||||
initIngest(0);
|
initIngest(0);
|
||||||
} else {
|
} else {
|
||||||
initIngest(1);
|
initIngest(1);
|
||||||
@ -191,13 +191,13 @@ class KeywordSearchEditListPanel extends javax.swing.JPanel implements ListSelec
|
|||||||
String changed = evt.getPropertyName();
|
String changed = evt.getPropertyName();
|
||||||
Object oldValue = evt.getOldValue();
|
Object oldValue = evt.getOldValue();
|
||||||
if (changed.equals(IngestModuleEvent.COMPLETED.toString() )
|
if (changed.equals(IngestModuleEvent.COMPLETED.toString() )
|
||||||
&& ((String) oldValue).equals(KeywordSearchIngestService.MODULE_NAME)) {
|
&& ((String) oldValue).equals(KeywordSearchIngestModule.MODULE_NAME)) {
|
||||||
initIngest(1);
|
initIngest(1);
|
||||||
} else if (changed.equals(IngestModuleEvent.STARTED.toString() )
|
} else if (changed.equals(IngestModuleEvent.STARTED.toString() )
|
||||||
&& ((String) oldValue).equals(KeywordSearchIngestService.MODULE_NAME)) {
|
&& ((String) oldValue).equals(KeywordSearchIngestModule.MODULE_NAME)) {
|
||||||
initIngest(0);
|
initIngest(0);
|
||||||
} else if (changed.equals(IngestModuleEvent.STOPPED.toString() )
|
} else if (changed.equals(IngestModuleEvent.STOPPED.toString() )
|
||||||
&& ((String) oldValue).equals(KeywordSearchIngestService.MODULE_NAME)) {
|
&& ((String) oldValue).equals(KeywordSearchIngestModule.MODULE_NAME)) {
|
||||||
initIngest(1);
|
initIngest(1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -249,7 +249,7 @@ class KeywordSearchEditListPanel extends javax.swing.JPanel implements ListSelec
|
|||||||
// Certain buttons will be disabled if ingest is ongoing on this list
|
// Certain buttons will be disabled if ingest is ongoing on this list
|
||||||
List<String> ingestLists = new ArrayList<String>();
|
List<String> ingestLists = new ArrayList<String>();
|
||||||
if (ingestOngoing) {
|
if (ingestOngoing) {
|
||||||
ingestLists = KeywordSearchIngestService.getDefault().getKeywordLists();
|
ingestLists = KeywordSearchIngestModule.getDefault().getKeywordLists();
|
||||||
}
|
}
|
||||||
boolean inIngest = !listSet ? false : ingestLists.contains(currentKeywordList.getName());
|
boolean inIngest = !listSet ? false : ingestLists.contains(currentKeywordList.getName());
|
||||||
|
|
||||||
|
@ -41,11 +41,12 @@ import org.openide.util.Cancellable;
|
|||||||
import org.sleuthkit.autopsy.casemodule.Case;
|
import org.sleuthkit.autopsy.casemodule.Case;
|
||||||
import org.sleuthkit.autopsy.coreutils.StopWatch;
|
import org.sleuthkit.autopsy.coreutils.StopWatch;
|
||||||
import org.sleuthkit.autopsy.coreutils.StringExtract.StringExtractUnicodeTable.SCRIPT;
|
import org.sleuthkit.autopsy.coreutils.StringExtract.StringExtractUnicodeTable.SCRIPT;
|
||||||
import org.sleuthkit.autopsy.ingest.IngestManagerProxy;
|
import org.sleuthkit.autopsy.ingest.IngestServices;
|
||||||
import org.sleuthkit.autopsy.ingest.IngestMessage;
|
import org.sleuthkit.autopsy.ingest.IngestMessage;
|
||||||
import org.sleuthkit.autopsy.ingest.IngestMessage.MessageType;
|
import org.sleuthkit.autopsy.ingest.IngestMessage.MessageType;
|
||||||
import org.sleuthkit.autopsy.ingest.IngestServiceAbstractFile;
|
import org.sleuthkit.autopsy.ingest.IngestModuleAbstractFile;
|
||||||
import org.sleuthkit.autopsy.ingest.ServiceDataEvent;
|
import org.sleuthkit.autopsy.ingest.IngestModuleInit;
|
||||||
|
import org.sleuthkit.autopsy.ingest.ModuleDataEvent;
|
||||||
import org.sleuthkit.autopsy.keywordsearch.Ingester.IngesterException;
|
import org.sleuthkit.autopsy.keywordsearch.Ingester.IngesterException;
|
||||||
import org.sleuthkit.datamodel.BlackboardArtifact;
|
import org.sleuthkit.datamodel.BlackboardArtifact;
|
||||||
import org.sleuthkit.datamodel.BlackboardArtifact.ARTIFACT_TYPE;
|
import org.sleuthkit.datamodel.BlackboardArtifact.ARTIFACT_TYPE;
|
||||||
@ -60,22 +61,22 @@ import org.sleuthkit.datamodel.TskData;
|
|||||||
import org.sleuthkit.datamodel.TskData.FileKnown;
|
import org.sleuthkit.datamodel.TskData.FileKnown;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* An ingest service on a file level Performs indexing of allocated and Solr
|
* An ingest module on a file level Performs indexing of allocated and Solr
|
||||||
* supported files, string extraction and indexing of unallocated and not Solr
|
* supported files, string extraction and indexing of unallocated and not Solr
|
||||||
* supported files Index commit is done periodically (determined by user set
|
* supported files Index commit is done periodically (determined by user set
|
||||||
* ingest update interval) Runs a periodic keyword / regular expression search
|
* ingest update interval) Runs a periodic keyword / regular expression search
|
||||||
* on currently configured lists for ingest and writes results to blackboard
|
* on currently configured lists for ingest and writes results to blackboard
|
||||||
* Reports interesting events to Inbox and to viewers
|
* Reports interesting events to Inbox and to viewers
|
||||||
*
|
*
|
||||||
* Registered as a service in layer.xml
|
* Registered as a module in layer.xml
|
||||||
*/
|
*/
|
||||||
public final class KeywordSearchIngestService implements IngestServiceAbstractFile {
|
public final class KeywordSearchIngestModule implements IngestModuleAbstractFile {
|
||||||
|
|
||||||
private static final Logger logger = Logger.getLogger(KeywordSearchIngestService.class.getName());
|
private static final Logger logger = Logger.getLogger(KeywordSearchIngestModule.class.getName());
|
||||||
public static final String MODULE_NAME = "Keyword Search";
|
public static final String MODULE_NAME = "Keyword Search";
|
||||||
public static final String MODULE_DESCRIPTION = "Performs file indexing and periodic search using keywords and regular expressions in lists.";
|
public static final String MODULE_DESCRIPTION = "Performs file indexing and periodic search using keywords and regular expressions in lists.";
|
||||||
private static KeywordSearchIngestService instance = null;
|
private static KeywordSearchIngestModule instance = null;
|
||||||
private IngestManagerProxy managerProxy;
|
private IngestServices services;
|
||||||
private Ingester ingester = null;
|
private Ingester ingester = null;
|
||||||
private volatile boolean commitIndex = false; //whether to commit index next time
|
private volatile boolean commitIndex = false; //whether to commit index next time
|
||||||
private volatile boolean runSearcher = false; //whether to run searcher next time
|
private volatile boolean runSearcher = false; //whether to run searcher next time
|
||||||
@ -95,7 +96,7 @@ public final class KeywordSearchIngestService implements IngestServiceAbstractFi
|
|||||||
private volatile int messageID = 0;
|
private volatile int messageID = 0;
|
||||||
private boolean processedFiles;
|
private boolean processedFiles;
|
||||||
private volatile boolean finalSearcherDone = true; //mark as done, until it's inited
|
private volatile boolean finalSearcherDone = true; //mark as done, until it's inited
|
||||||
private final String hashDBServiceName = "Hash Lookup"; //NOTE this needs to match the HashDB service getName()
|
private final String hashDBModuleName = "Hash Lookup"; //NOTE this needs to match the HashDB module getName()
|
||||||
private SleuthkitCase caseHandle = null;
|
private SleuthkitCase caseHandle = null;
|
||||||
private boolean skipKnown = true;
|
private boolean skipKnown = true;
|
||||||
private boolean initialized = false;
|
private boolean initialized = false;
|
||||||
@ -111,20 +112,20 @@ public final class KeywordSearchIngestService implements IngestServiceAbstractFi
|
|||||||
private Map<Long, IngestStatus> ingestStatus;
|
private Map<Long, IngestStatus> ingestStatus;
|
||||||
|
|
||||||
//private constructor to ensure singleton instance
|
//private constructor to ensure singleton instance
|
||||||
private KeywordSearchIngestService() {
|
private KeywordSearchIngestModule() {
|
||||||
//set default script
|
//set default script
|
||||||
stringExtractScripts.add(SCRIPT.LATIN_1);
|
stringExtractScripts.add(SCRIPT.LATIN_1);
|
||||||
stringExtractScripts.add(SCRIPT.LATIN_2);
|
stringExtractScripts.add(SCRIPT.LATIN_2);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns singleton instance of the service, creates one if needed
|
* Returns singleton instance of the module, creates one if needed
|
||||||
*
|
*
|
||||||
* @return instance of the service
|
* @return instance of the module
|
||||||
*/
|
*/
|
||||||
public static synchronized KeywordSearchIngestService getDefault() {
|
public static synchronized KeywordSearchIngestModule getDefault() {
|
||||||
if (instance == null) {
|
if (instance == null) {
|
||||||
instance = new KeywordSearchIngestService();
|
instance = new KeywordSearchIngestModule();
|
||||||
}
|
}
|
||||||
return instance;
|
return instance;
|
||||||
}
|
}
|
||||||
@ -145,13 +146,13 @@ public final class KeywordSearchIngestService implements IngestServiceAbstractFi
|
|||||||
return ProcessResult.OK;
|
return ProcessResult.OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
//check if we should index meta-data only when 1) it is known 2) HashDb service errored on it
|
//check if we should index meta-data only when 1) it is known 2) HashDb module errored on it
|
||||||
IngestServiceAbstractFile.ProcessResult hashDBResult = managerProxy.getAbstractFileServiceResult(hashDBServiceName);
|
IngestModuleAbstractFile.ProcessResult hashDBResult = services.getAbstractFileModuleResult(hashDBModuleName);
|
||||||
//logger.log(Level.INFO, "hashdb result: " + hashDBResult + "file: " + AbstractFile.getName());
|
//logger.log(Level.INFO, "hashdb result: " + hashDBResult + "file: " + AbstractFile.getName());
|
||||||
if (hashDBResult == IngestServiceAbstractFile.ProcessResult.ERROR) {
|
if (hashDBResult == IngestModuleAbstractFile.ProcessResult.ERROR) {
|
||||||
//index meta-data only
|
//index meta-data only
|
||||||
indexer.indexFile(abstractFile, false);
|
indexer.indexFile(abstractFile, false);
|
||||||
//notify depending service that keyword search (would) encountered error for this file
|
//notify depending module that keyword search (would) encountered error for this file
|
||||||
return ProcessResult.ERROR;
|
return ProcessResult.ERROR;
|
||||||
}
|
}
|
||||||
else if (skipKnown && abstractFile.accept(getIsFileKnown) == true) {
|
else if (skipKnown && abstractFile.accept(getIsFileKnown) == true) {
|
||||||
@ -230,7 +231,7 @@ public final class KeywordSearchIngestService implements IngestServiceAbstractFi
|
|||||||
finalSearcher.execute();
|
finalSearcher.execute();
|
||||||
} else {
|
} else {
|
||||||
finalSearcherDone = true;
|
finalSearcherDone = true;
|
||||||
managerProxy.postMessage(IngestMessage.createMessage(++messageID, MessageType.INFO, this, "Completed"));
|
services.postMessage(IngestMessage.createMessage(++messageID, MessageType.INFO, this, "Completed"));
|
||||||
}
|
}
|
||||||
|
|
||||||
//log number of files / chunks in index
|
//log number of files / chunks in index
|
||||||
@ -289,20 +290,19 @@ public final class KeywordSearchIngestService implements IngestServiceAbstractFi
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Initializes the service for new ingest run Sets up threads, timers,
|
* Initializes the module for new ingest run Sets up threads, timers,
|
||||||
* retrieves settings, keyword lists to run on
|
* retrieves settings, keyword lists to run on
|
||||||
*
|
*
|
||||||
* @param managerProxy
|
* @param services
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public void init(IngestManagerProxy managerProxy) {
|
public void init(IngestModuleInit initContext) {
|
||||||
logger.log(Level.INFO, "init()");
|
logger.log(Level.INFO, "init()");
|
||||||
|
services = IngestServices.getDefault();
|
||||||
initialized = false;
|
initialized = false;
|
||||||
|
|
||||||
caseHandle = Case.getCurrentCase().getSleuthkitCase();
|
caseHandle = Case.getCurrentCase().getSleuthkitCase();
|
||||||
|
|
||||||
this.managerProxy = managerProxy;
|
|
||||||
|
|
||||||
ingester = Server.getIngester();
|
ingester = Server.getIngester();
|
||||||
|
|
||||||
//initialize extractors
|
//initialize extractors
|
||||||
@ -330,7 +330,7 @@ public final class KeywordSearchIngestService implements IngestServiceAbstractFi
|
|||||||
initKeywords();
|
initKeywords();
|
||||||
|
|
||||||
if (keywords.isEmpty() || keywordLists.isEmpty()) {
|
if (keywords.isEmpty() || keywordLists.isEmpty()) {
|
||||||
managerProxy.postMessage(IngestMessage.createWarningMessage(++messageID, instance, "No keywords in keyword list.", "Only indexing will be done and and keyword search will be skipped (it can be executed later again as ingest or using toolbar search feature)."));
|
services.postMessage(IngestMessage.createWarningMessage(++messageID, instance, "No keywords in keyword list.", "Only indexing will be done and and keyword search will be skipped (it can be executed later again as ingest or using toolbar search feature)."));
|
||||||
}
|
}
|
||||||
|
|
||||||
processedFiles = false;
|
processedFiles = false;
|
||||||
@ -341,7 +341,7 @@ public final class KeywordSearchIngestService implements IngestServiceAbstractFi
|
|||||||
|
|
||||||
indexer = new Indexer();
|
indexer = new Indexer();
|
||||||
|
|
||||||
final int updateIntervalMs = managerProxy.getUpdateFrequency() * 60 * 1000;
|
final int updateIntervalMs = services.getUpdateFrequency() * 60 * 1000;
|
||||||
logger.log(Level.INFO, "Using commit interval (ms): " + updateIntervalMs);
|
logger.log(Level.INFO, "Using commit interval (ms): " + updateIntervalMs);
|
||||||
logger.log(Level.INFO, "Using searcher interval (ms): " + updateIntervalMs);
|
logger.log(Level.INFO, "Using searcher interval (ms): " + updateIntervalMs);
|
||||||
|
|
||||||
@ -353,12 +353,12 @@ public final class KeywordSearchIngestService implements IngestServiceAbstractFi
|
|||||||
commitTimer.start();
|
commitTimer.start();
|
||||||
searchTimer.start();
|
searchTimer.start();
|
||||||
|
|
||||||
managerProxy.postMessage(IngestMessage.createMessage(++messageID, MessageType.INFO, this, "Started"));
|
services.postMessage(IngestMessage.createMessage(++messageID, MessageType.INFO, this, "Started"));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ServiceType getType() {
|
public ModuleType getType() {
|
||||||
return ServiceType.AbstractFile;
|
return ModuleType.AbstractFile;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -390,7 +390,7 @@ public final class KeywordSearchIngestService implements IngestServiceAbstractFi
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The services maintains background threads, return true if background
|
* The modules maintains background threads, return true if background
|
||||||
* threads are running or there are pending tasks to be run in the future,
|
* threads are running or there are pending tasks to be run in the future,
|
||||||
* such as the final search post-ingest completion
|
* such as the final search post-ingest completion
|
||||||
*
|
*
|
||||||
@ -453,7 +453,7 @@ public final class KeywordSearchIngestService implements IngestServiceAbstractFi
|
|||||||
msg.append("<br />Skipped files: ").append(skipped).append("<br />");
|
msg.append("<br />Skipped files: ").append(skipped).append("<br />");
|
||||||
String indexStats = msg.toString();
|
String indexStats = msg.toString();
|
||||||
logger.log(Level.INFO, "Keyword Indexing Completed: " + indexStats);
|
logger.log(Level.INFO, "Keyword Indexing Completed: " + indexStats);
|
||||||
managerProxy.postMessage(IngestMessage.createMessage(++messageID, MessageType.INFO, this, "Keyword Indexing Completed", indexStats));
|
services.postMessage(IngestMessage.createMessage(++messageID, MessageType.INFO, this, "Keyword Indexing Completed", indexStats));
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -910,7 +910,7 @@ public final class KeywordSearchIngestService implements IngestServiceAbstractFi
|
|||||||
//check if should send messages on hits on this list
|
//check if should send messages on hits on this list
|
||||||
if (list.getIngestMessages()) //post ingest inbox msg
|
if (list.getIngestMessages()) //post ingest inbox msg
|
||||||
{
|
{
|
||||||
managerProxy.postMessage(IngestMessage.createDataMessage(++messageID, instance, subjectSb.toString(), detailsSb.toString(), uniqueKey, written.getArtifact()));
|
services.postMessage(IngestMessage.createDataMessage(++messageID, instance, subjectSb.toString(), detailsSb.toString(), uniqueKey, written.getArtifact()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -919,7 +919,7 @@ public final class KeywordSearchIngestService implements IngestServiceAbstractFi
|
|||||||
|
|
||||||
//update artifact browser
|
//update artifact browser
|
||||||
if (!newArtifacts.isEmpty()) {
|
if (!newArtifacts.isEmpty()) {
|
||||||
IngestManagerProxy.fireServiceDataEvent(new ServiceDataEvent(MODULE_NAME, ARTIFACT_TYPE.TSK_KEYWORD_HIT, newArtifacts));
|
services.fireModuleDataEvent(new ModuleDataEvent(MODULE_NAME, ARTIFACT_TYPE.TSK_KEYWORD_HIT, newArtifacts));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
progress.progress(queryStr, ++numSearched);
|
progress.progress(queryStr, ++numSearched);
|
||||||
@ -987,7 +987,7 @@ public final class KeywordSearchIngestService implements IngestServiceAbstractFi
|
|||||||
//reset current resuls earlier to potentially garbage collect sooner
|
//reset current resuls earlier to potentially garbage collect sooner
|
||||||
currentResults = new HashMap<Keyword, List<Long>>();
|
currentResults = new HashMap<Keyword, List<Long>>();
|
||||||
|
|
||||||
managerProxy.postMessage(IngestMessage.createMessage(++messageID, MessageType.INFO, KeywordSearchIngestService.instance, "Completed"));
|
services.postMessage(IngestMessage.createMessage(++messageID, MessageType.INFO, KeywordSearchIngestModule.instance, "Completed"));
|
||||||
} else {
|
} else {
|
||||||
//start counting time for a new searcher to start
|
//start counting time for a new searcher to start
|
||||||
//unless final searcher is pending
|
//unless final searcher is pending
|
||||||
@ -1039,10 +1039,10 @@ public final class KeywordSearchIngestService implements IngestServiceAbstractFi
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set the skip known files setting on the service
|
* Set the skip known files setting on the module
|
||||||
*
|
*
|
||||||
* @param skip true if skip, otherwise, will process known files as well, as
|
* @param skip true if skip, otherwise, will process known files as well, as
|
||||||
* reported by HashDB service
|
* reported by HashDB module
|
||||||
*/
|
*/
|
||||||
void setSkipKnown(boolean skip) {
|
void setSkipKnown(boolean skip) {
|
||||||
this.skipKnown = skip;
|
this.skipKnown = skip;
|
@ -163,7 +163,7 @@ public class KeywordSearchIngestSimplePanel extends javax.swing.JPanel {
|
|||||||
|
|
||||||
private void reloadLangs() {
|
private void reloadLangs() {
|
||||||
//TODO multiple
|
//TODO multiple
|
||||||
List<SCRIPT> scripts = KeywordSearchIngestService.getDefault().getStringExtractScripts();
|
List<SCRIPT> scripts = KeywordSearchIngestModule.getDefault().getStringExtractScripts();
|
||||||
StringBuilder langs = new StringBuilder();
|
StringBuilder langs = new StringBuilder();
|
||||||
langs.append("<html>");
|
langs.append("<html>");
|
||||||
for (SCRIPT s : scripts) {
|
for (SCRIPT s : scripts) {
|
||||||
|
@ -159,7 +159,7 @@ class KeywordSearchListsViewerPanel extends AbstractKeywordSearchPerformer {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
if(IngestManager.getDefault().isServiceRunning(KeywordSearchIngestService.getDefault())) {
|
if(IngestManager.getDefault().isModuleRunning(KeywordSearchIngestModule.getDefault())) {
|
||||||
initIngest(true);
|
initIngest(true);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
@ -173,15 +173,15 @@ class KeywordSearchListsViewerPanel extends AbstractKeywordSearchPerformer {
|
|||||||
String changed = evt.getPropertyName();
|
String changed = evt.getPropertyName();
|
||||||
Object oldValue = evt.getOldValue();
|
Object oldValue = evt.getOldValue();
|
||||||
if(changed.equals(IngestModuleEvent.COMPLETED.toString() ) &&
|
if(changed.equals(IngestModuleEvent.COMPLETED.toString() ) &&
|
||||||
((String) oldValue).equals(KeywordSearchIngestService.MODULE_NAME)) {
|
((String) oldValue).equals(KeywordSearchIngestModule.MODULE_NAME)) {
|
||||||
initIngest(false);
|
initIngest(false);
|
||||||
}
|
}
|
||||||
else if(changed.equals(IngestModuleEvent.STARTED.toString() ) &&
|
else if(changed.equals(IngestModuleEvent.STARTED.toString() ) &&
|
||||||
((String) oldValue).equals(KeywordSearchIngestService.MODULE_NAME)) {
|
((String) oldValue).equals(KeywordSearchIngestModule.MODULE_NAME)) {
|
||||||
initIngest(true);
|
initIngest(true);
|
||||||
}
|
}
|
||||||
else if(changed.equals(IngestModuleEvent.STOPPED.toString() ) &&
|
else if(changed.equals(IngestModuleEvent.STOPPED.toString() ) &&
|
||||||
((String) oldValue).equals(KeywordSearchIngestService.MODULE_NAME)) {
|
((String) oldValue).equals(KeywordSearchIngestModule.MODULE_NAME)) {
|
||||||
initIngest(false);
|
initIngest(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -410,7 +410,7 @@ class KeywordSearchListsViewerPanel extends AbstractKeywordSearchPerformer {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isCellEditable(int rowIndex, int columnIndex) {
|
public boolean isCellEditable(int rowIndex, int columnIndex) {
|
||||||
List<String> locked = KeywordSearchIngestService.getDefault().getKeywordLists();
|
List<String> locked = KeywordSearchIngestModule.getDefault().getKeywordLists();
|
||||||
return (columnIndex == 0 && (!ingestRunning || !locked.contains((String)getValueAt(rowIndex, 1))));
|
return (columnIndex == 0 && (!ingestRunning || !locked.contains((String)getValueAt(rowIndex, 1))));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -618,7 +618,7 @@ class KeywordSearchListsViewerPanel extends AbstractKeywordSearchPerformer {
|
|||||||
this.setVerticalAlignment(JCheckBox.CENTER);
|
this.setVerticalAlignment(JCheckBox.CENTER);
|
||||||
|
|
||||||
String name = (String) table.getModel().getValueAt(row, 1);
|
String name = (String) table.getModel().getValueAt(row, 1);
|
||||||
List<String> locked = KeywordSearchIngestService.getDefault().getKeywordLists();
|
List<String> locked = KeywordSearchIngestModule.getDefault().getKeywordLists();
|
||||||
setEnabled(!locked.contains(name) || !ingestRunning);
|
setEnabled(!locked.contains(name) || !ingestRunning);
|
||||||
Boolean selected = (Boolean) table.getModel().getValueAt(row, 0);
|
Boolean selected = (Boolean) table.getModel().getValueAt(row, 0);
|
||||||
setSelected(selected);
|
setSelected(selected);
|
||||||
|
@ -167,13 +167,28 @@ public class KeywordSearchListsXML extends KeywordSearchListsAbstract{
|
|||||||
final String name = listEl.getAttribute(LIST_NAME_ATTR);
|
final String name = listEl.getAttribute(LIST_NAME_ATTR);
|
||||||
final String created = listEl.getAttribute(LIST_CREATE_ATTR);
|
final String created = listEl.getAttribute(LIST_CREATE_ATTR);
|
||||||
final String modified = listEl.getAttribute(LIST_MOD_ATTR);
|
final String modified = listEl.getAttribute(LIST_MOD_ATTR);
|
||||||
final String useForIngest = listEl.getAttribute(LIST_USE_FOR_INGEST);
|
|
||||||
final String ingestMessages = listEl.getAttribute(LIST_INGEST_MSGS);
|
//set these bools to true by default, if they don't exist in XML
|
||||||
|
Boolean useForIngestBool;
|
||||||
|
Boolean ingestMessagesBool;
|
||||||
|
|
||||||
|
if (listEl.hasAttribute(LIST_USE_FOR_INGEST) ) {
|
||||||
|
useForIngestBool = Boolean.parseBoolean(listEl.getAttribute(LIST_USE_FOR_INGEST));
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
useForIngestBool = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (listEl.hasAttribute(LIST_INGEST_MSGS)) {
|
||||||
|
ingestMessagesBool = Boolean.parseBoolean(listEl.getAttribute(LIST_INGEST_MSGS));
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
ingestMessagesBool = true;
|
||||||
|
}
|
||||||
|
|
||||||
Date createdDate = dateFormatter.parse(created);
|
Date createdDate = dateFormatter.parse(created);
|
||||||
Date modDate = dateFormatter.parse(modified);
|
Date modDate = dateFormatter.parse(modified);
|
||||||
Boolean useForIngestBool = Boolean.parseBoolean(useForIngest);
|
|
||||||
Boolean ingestMessagesBool = Boolean.parseBoolean(ingestMessages);
|
|
||||||
List<Keyword> words = new ArrayList<Keyword>();
|
List<Keyword> words = new ArrayList<Keyword>();
|
||||||
KeywordSearchList list = new KeywordSearchList(name, createdDate, modDate, useForIngestBool, ingestMessagesBool, words);
|
KeywordSearchList list = new KeywordSearchList(name, createdDate, modDate, useForIngestBool, ingestMessagesBool, words);
|
||||||
|
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
<?xml version="1.1" encoding="UTF-8" ?>
|
<?xml version="1.0" encoding="UTF-8" ?>
|
||||||
|
|
||||||
<Form version="1.5" maxVersion="1.7" type="org.netbeans.modules.form.forminfo.JPanelFormInfo">
|
<Form version="1.5" maxVersion="1.7" type="org.netbeans.modules.form.forminfo.JPanelFormInfo">
|
||||||
<NonVisualComponents>
|
<NonVisualComponents>
|
||||||
@ -88,10 +88,7 @@
|
|||||||
</DimensionLayout>
|
</DimensionLayout>
|
||||||
<DimensionLayout dim="1">
|
<DimensionLayout dim="1">
|
||||||
<Group type="103" groupAlignment="0" attributes="0">
|
<Group type="103" groupAlignment="0" attributes="0">
|
||||||
<Group type="102" alignment="1" attributes="0">
|
<Component id="listsButton" alignment="1" max="32767" attributes="1"/>
|
||||||
<EmptySpace min="-2" pref="0" max="-2" attributes="0"/>
|
|
||||||
<Component id="listsButton" max="32767" attributes="1"/>
|
|
||||||
</Group>
|
|
||||||
<Component id="searchBoxPanel" alignment="0" pref="27" max="32767" attributes="2"/>
|
<Component id="searchBoxPanel" alignment="0" pref="27" max="32767" attributes="2"/>
|
||||||
</Group>
|
</Group>
|
||||||
</DimensionLayout>
|
</DimensionLayout>
|
||||||
@ -125,9 +122,9 @@
|
|||||||
</DimensionLayout>
|
</DimensionLayout>
|
||||||
<DimensionLayout dim="1">
|
<DimensionLayout dim="1">
|
||||||
<Group type="103" groupAlignment="0" attributes="0">
|
<Group type="103" groupAlignment="0" attributes="0">
|
||||||
<Component id="searchBox" alignment="0" pref="25" max="32767" attributes="3"/>
|
<Component id="searchBox" alignment="0" max="32767" attributes="3"/>
|
||||||
<Component id="settingsLabel" alignment="0" pref="25" max="32767" attributes="1"/>
|
<Component id="settingsLabel" alignment="0" max="32767" attributes="1"/>
|
||||||
<Component id="searchButton" alignment="0" pref="25" max="32767" attributes="1"/>
|
<Component id="searchButton" alignment="0" max="32767" attributes="1"/>
|
||||||
</Group>
|
</Group>
|
||||||
</DimensionLayout>
|
</DimensionLayout>
|
||||||
</Layout>
|
</Layout>
|
||||||
|
@ -52,13 +52,24 @@ public class KeywordSearchPanel extends AbstractKeywordSearchPerformer {
|
|||||||
private KeywordPropertyChangeListener listener;
|
private KeywordPropertyChangeListener listener;
|
||||||
private boolean active = false;
|
private boolean active = false;
|
||||||
private boolean entered = false;
|
private boolean entered = false;
|
||||||
|
private static KeywordSearchPanel instance;
|
||||||
|
|
||||||
/** Creates new form KeywordSearchPanel */
|
/** Creates new form KeywordSearchPanel */
|
||||||
public KeywordSearchPanel() {
|
private KeywordSearchPanel() {
|
||||||
initComponents();
|
initComponents();
|
||||||
customizeComponents();
|
customizeComponents();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return the default instance KeywordSearchPanel
|
||||||
|
*/
|
||||||
|
public static KeywordSearchPanel getDefault() {
|
||||||
|
if (instance == null) {
|
||||||
|
instance = new KeywordSearchPanel();
|
||||||
|
}
|
||||||
|
return instance;
|
||||||
|
}
|
||||||
|
|
||||||
private void customizeComponents() {
|
private void customizeComponents() {
|
||||||
|
|
||||||
listener = new KeywordPropertyChangeListener();
|
listener = new KeywordPropertyChangeListener();
|
||||||
|
@ -42,8 +42,8 @@ import org.sleuthkit.autopsy.corecomponentinterfaces.DataResultViewer;
|
|||||||
import org.sleuthkit.autopsy.datamodel.AbstractFsContentNode;
|
import org.sleuthkit.autopsy.datamodel.AbstractFsContentNode;
|
||||||
import org.sleuthkit.autopsy.datamodel.AbstractFsContentNode.FsContentPropertyType;
|
import org.sleuthkit.autopsy.datamodel.AbstractFsContentNode.FsContentPropertyType;
|
||||||
import org.sleuthkit.autopsy.datamodel.KeyValueNode;
|
import org.sleuthkit.autopsy.datamodel.KeyValueNode;
|
||||||
import org.sleuthkit.autopsy.ingest.IngestManagerProxy;
|
import org.sleuthkit.autopsy.ingest.IngestServices;
|
||||||
import org.sleuthkit.autopsy.ingest.ServiceDataEvent;
|
import org.sleuthkit.autopsy.ingest.ModuleDataEvent;
|
||||||
import org.sleuthkit.autopsy.keywordsearch.KeywordSearchQueryManager.Presentation;
|
import org.sleuthkit.autopsy.keywordsearch.KeywordSearchQueryManager.Presentation;
|
||||||
import org.sleuthkit.datamodel.AbstractFile;
|
import org.sleuthkit.datamodel.AbstractFile;
|
||||||
import org.sleuthkit.datamodel.BlackboardArtifact;
|
import org.sleuthkit.datamodel.BlackboardArtifact;
|
||||||
@ -536,7 +536,7 @@ public class KeywordSearchResultFactory extends ChildFactory<KeyValueQuery> {
|
|||||||
|
|
||||||
|
|
||||||
if (!this.isCancelled() && !na.isEmpty()) {
|
if (!this.isCancelled() && !na.isEmpty()) {
|
||||||
IngestManagerProxy.fireServiceDataEvent(new ServiceDataEvent(KeywordSearchIngestService.MODULE_NAME, ARTIFACT_TYPE.TSK_KEYWORD_HIT, na));
|
IngestServices.getDefault().fireModuleDataEvent(new ModuleDataEvent(KeywordSearchIngestModule.MODULE_NAME, ARTIFACT_TYPE.TSK_KEYWORD_HIT, na));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -126,7 +126,7 @@ public class LuceneQuery implements KeywordSearchQuery {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public KeywordWriteResult writeToBlackBoard(String termHit, AbstractFile newFsHit, String snippet, String listName) {
|
public KeywordWriteResult writeToBlackBoard(String termHit, AbstractFile newFsHit, String snippet, String listName) {
|
||||||
final String MODULE_NAME = KeywordSearchIngestService.MODULE_NAME;
|
final String MODULE_NAME = KeywordSearchIngestModule.MODULE_NAME;
|
||||||
|
|
||||||
KeywordWriteResult writeResult = null;
|
KeywordWriteResult writeResult = null;
|
||||||
Collection<BlackboardAttribute> attributes = new ArrayList<BlackboardAttribute>();
|
Collection<BlackboardAttribute> attributes = new ArrayList<BlackboardAttribute>();
|
||||||
|
@ -160,7 +160,7 @@ public class TermComponentQuery implements KeywordSearchQuery {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public KeywordWriteResult writeToBlackBoard(String termHit, AbstractFile newFsHit, String snippet, String listName) {
|
public KeywordWriteResult writeToBlackBoard(String termHit, AbstractFile newFsHit, String snippet, String listName) {
|
||||||
final String MODULE_NAME = KeywordSearchIngestService.MODULE_NAME;
|
final String MODULE_NAME = KeywordSearchIngestModule.MODULE_NAME;
|
||||||
|
|
||||||
//there is match actually in this file, create artifact only then
|
//there is match actually in this file, create artifact only then
|
||||||
BlackboardArtifact bba = null;
|
BlackboardArtifact bba = null;
|
||||||
|
@ -28,9 +28,9 @@
|
|||||||
<attr name="instanceCreate" methodvalue="org.sleuthkit.autopsy.keywordsearch.HighlightedMatchesSource.getDefault"/>
|
<attr name="instanceCreate" methodvalue="org.sleuthkit.autopsy.keywordsearch.HighlightedMatchesSource.getDefault"/>
|
||||||
<attr name="position" intvalue="250"/>
|
<attr name="position" intvalue="250"/>
|
||||||
</file>
|
</file>
|
||||||
<file name="org-sleuthkit-autopsy-keywordsearch-KeywordSearchIngestService.instance">
|
<file name="org-sleuthkit-autopsy-keywordsearch-KeywordSearchIngestModule.instance">
|
||||||
<attr name="instanceOf" stringvalue="org.sleuthkit.autopsy.ingest.IngestServiceAbstractFile"/>
|
<attr name="instanceOf" stringvalue="org.sleuthkit.autopsy.ingest.IngestModuleAbstractFile"/>
|
||||||
<attr name="instanceCreate" methodvalue="org.sleuthkit.autopsy.keywordsearch.KeywordSearchIngestService.getDefault"/>
|
<attr name="instanceCreate" methodvalue="org.sleuthkit.autopsy.keywordsearch.KeywordSearchIngestModule.getDefault"/>
|
||||||
<attr name="position" intvalue="300"/>
|
<attr name="position" intvalue="300"/>
|
||||||
</file>
|
</file>
|
||||||
<!--<file name="org-sleuthkit-autopsy-keywordsearch-KeywordSearchDataExplorer.instance">
|
<!--<file name="org-sleuthkit-autopsy-keywordsearch-KeywordSearchDataExplorer.instance">
|
||||||
|
4
NEWS.txt
4
NEWS.txt
@ -1,4 +1,4 @@
|
|||||||
3.0.0 (August 29, 2012)
|
3.0.0b5 (September 12, 2012)
|
||||||
Funded by US Army Intelligence Center of Excellence (USAICoE):
|
Funded by US Army Intelligence Center of Excellence (USAICoE):
|
||||||
|
|
||||||
New features:
|
New features:
|
||||||
@ -14,12 +14,14 @@ New features:
|
|||||||
- Basic file bookmarks support.
|
- Basic file bookmarks support.
|
||||||
- Body file report.
|
- Body file report.
|
||||||
- Improved UI.
|
- Improved UI.
|
||||||
|
- Updated Ingest Module API.
|
||||||
|
|
||||||
Bugfixes:
|
Bugfixes:
|
||||||
- Keyword search memory usage improvements.
|
- Keyword search memory usage improvements.
|
||||||
- Directory tree now shows which directories have no children before user clicks.
|
- Directory tree now shows which directories have no children before user clicks.
|
||||||
- Fixed bug when recent cases would not get updated.
|
- Fixed bug when recent cases would not get updated.
|
||||||
- Fixed a bug when sometimes a case would get deleted.
|
- Fixed a bug when sometimes a case would get deleted.
|
||||||
|
- Fixed occasional Media View crashes.
|
||||||
|
|
||||||
3.0.0b4 (June 29, 2012)
|
3.0.0b4 (June 29, 2012)
|
||||||
Funded by US Army Intelligence Center of Excellence (USAICoE):
|
Funded by US Army Intelligence Center of Excellence (USAICoE):
|
||||||
|
@ -24,8 +24,7 @@ import com.google.gson.JsonArray;
|
|||||||
import com.google.gson.JsonElement;
|
import com.google.gson.JsonElement;
|
||||||
import com.google.gson.JsonObject;
|
import com.google.gson.JsonObject;
|
||||||
import com.google.gson.JsonParser;
|
import com.google.gson.JsonParser;
|
||||||
import javax.swing.JPanel;
|
import org.sleuthkit.autopsy.ingest.IngestServices;
|
||||||
import org.sleuthkit.autopsy.ingest.IngestManagerProxy;
|
|
||||||
import org.sleuthkit.datamodel.FsContent;
|
import org.sleuthkit.datamodel.FsContent;
|
||||||
import org.sleuthkit.autopsy.datamodel.ContentUtils;
|
import org.sleuthkit.autopsy.datamodel.ContentUtils;
|
||||||
import java.util.logging.Level;
|
import java.util.logging.Level;
|
||||||
@ -35,9 +34,9 @@ import java.io.File;
|
|||||||
import java.io.FileReader;
|
import java.io.FileReader;
|
||||||
import org.sleuthkit.autopsy.coreutils.DecodeUtil;
|
import org.sleuthkit.autopsy.coreutils.DecodeUtil;
|
||||||
import org.sleuthkit.autopsy.ingest.IngestImageWorkerController;
|
import org.sleuthkit.autopsy.ingest.IngestImageWorkerController;
|
||||||
import org.sleuthkit.autopsy.ingest.IngestManager;
|
import org.sleuthkit.autopsy.ingest.IngestModuleImage;
|
||||||
import org.sleuthkit.autopsy.ingest.IngestServiceImage;
|
import org.sleuthkit.autopsy.ingest.IngestModuleInit;
|
||||||
import org.sleuthkit.autopsy.ingest.ServiceDataEvent;
|
import org.sleuthkit.autopsy.ingest.ModuleDataEvent;
|
||||||
import org.sleuthkit.datamodel.BlackboardArtifact;
|
import org.sleuthkit.datamodel.BlackboardArtifact;
|
||||||
import org.sleuthkit.datamodel.BlackboardArtifact.ARTIFACT_TYPE;
|
import org.sleuthkit.datamodel.BlackboardArtifact.ARTIFACT_TYPE;
|
||||||
import org.sleuthkit.datamodel.BlackboardAttribute;
|
import org.sleuthkit.datamodel.BlackboardAttribute;
|
||||||
@ -45,10 +44,9 @@ import org.sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE;
|
|||||||
import org.sleuthkit.datamodel.Image;
|
import org.sleuthkit.datamodel.Image;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
* Chrome recent activity extraction
|
||||||
* @author Alex
|
|
||||||
*/
|
*/
|
||||||
public class Chrome extends Extract implements IngestServiceImage {
|
public class Chrome extends Extract implements IngestModuleImage {
|
||||||
|
|
||||||
private static final String chquery = "SELECT urls.url, urls.title, urls.visit_count, urls.typed_count, "
|
private static final String chquery = "SELECT urls.url, urls.title, urls.visit_count, urls.typed_count, "
|
||||||
+ "last_visit_time, urls.hidden, visits.visit_time, (SELECT urls.url FROM urls WHERE urls.id=visits.url) as from_visit, visits.transition FROM urls, visits WHERE urls.id = visits.url";
|
+ "last_visit_time, urls.hidden, visits.visit_time, (SELECT urls.url FROM urls WHERE urls.id=visits.url) as from_visit, visits.transition FROM urls, visits WHERE urls.id = visits.url";
|
||||||
@ -59,6 +57,8 @@ public class Chrome extends Extract implements IngestServiceImage {
|
|||||||
private final Logger logger = Logger.getLogger(this.getClass().getName());
|
private final Logger logger = Logger.getLogger(this.getClass().getName());
|
||||||
public int ChromeCount = 0;
|
public int ChromeCount = 0;
|
||||||
|
|
||||||
|
private IngestServices services;
|
||||||
|
|
||||||
public Chrome() {
|
public Chrome() {
|
||||||
moduleName = "Chrome";
|
moduleName = "Chrome";
|
||||||
}
|
}
|
||||||
@ -114,7 +114,8 @@ public class Chrome extends Extract implements IngestServiceImage {
|
|||||||
j++;
|
j++;
|
||||||
dbFile.delete();
|
dbFile.delete();
|
||||||
}
|
}
|
||||||
IngestManagerProxy.fireServiceDataEvent(new ServiceDataEvent("Recent Activity", BlackboardArtifact.ARTIFACT_TYPE.TSK_WEB_HISTORY));
|
|
||||||
|
services.fireModuleDataEvent(new ModuleDataEvent("Recent Activity", BlackboardArtifact.ARTIFACT_TYPE.TSK_WEB_HISTORY));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -174,7 +175,8 @@ public class Chrome extends Extract implements IngestServiceImage {
|
|||||||
j++;
|
j++;
|
||||||
dbFile.delete();
|
dbFile.delete();
|
||||||
}
|
}
|
||||||
IngestManagerProxy.fireServiceDataEvent(new ServiceDataEvent("Recent Activity", BlackboardArtifact.ARTIFACT_TYPE.TSK_WEB_BOOKMARK));
|
|
||||||
|
services.fireModuleDataEvent(new ModuleDataEvent("Recent Activity", BlackboardArtifact.ARTIFACT_TYPE.TSK_WEB_BOOKMARK));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -223,7 +225,8 @@ public class Chrome extends Extract implements IngestServiceImage {
|
|||||||
j++;
|
j++;
|
||||||
dbFile.delete();
|
dbFile.delete();
|
||||||
}
|
}
|
||||||
IngestManagerProxy.fireServiceDataEvent(new ServiceDataEvent("Recent Activity", BlackboardArtifact.ARTIFACT_TYPE.TSK_WEB_COOKIE));
|
|
||||||
|
services.fireModuleDataEvent(new ModuleDataEvent("Recent Activity", BlackboardArtifact.ARTIFACT_TYPE.TSK_WEB_COOKIE));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -274,7 +277,8 @@ public class Chrome extends Extract implements IngestServiceImage {
|
|||||||
j++;
|
j++;
|
||||||
dbFile.delete();
|
dbFile.delete();
|
||||||
}
|
}
|
||||||
IngestManagerProxy.fireServiceDataEvent(new ServiceDataEvent("Recent Activity", BlackboardArtifact.ARTIFACT_TYPE.TSK_WEB_DOWNLOAD));
|
|
||||||
|
services.fireModuleDataEvent(new ModuleDataEvent("Recent Activity", BlackboardArtifact.ARTIFACT_TYPE.TSK_WEB_DOWNLOAD));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -321,13 +325,14 @@ public class Chrome extends Extract implements IngestServiceImage {
|
|||||||
j++;
|
j++;
|
||||||
dbFile.delete();
|
dbFile.delete();
|
||||||
}
|
}
|
||||||
IngestManagerProxy.fireServiceDataEvent(new ServiceDataEvent("Recent Activity", BlackboardArtifact.ARTIFACT_TYPE.TSK_WEB_HISTORY));
|
|
||||||
|
services.fireModuleDataEvent(new ModuleDataEvent("Recent Activity", BlackboardArtifact.ARTIFACT_TYPE.TSK_WEB_HISTORY));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void init(IngestManagerProxy managerProxy) {
|
public void init(IngestModuleInit initContext) {
|
||||||
throw new UnsupportedOperationException("Not supported yet.");
|
services = IngestServices.getDefault();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -346,8 +351,8 @@ public class Chrome extends Extract implements IngestServiceImage {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ServiceType getType() {
|
public ModuleType getType() {
|
||||||
return ServiceType.Image;
|
return ModuleType.Image;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -28,10 +28,10 @@ import java.util.*;
|
|||||||
import java.util.logging.Level;
|
import java.util.logging.Level;
|
||||||
import java.util.logging.Logger;
|
import java.util.logging.Logger;
|
||||||
import org.sleuthkit.autopsy.casemodule.Case;
|
import org.sleuthkit.autopsy.casemodule.Case;
|
||||||
import org.sleuthkit.autopsy.ingest.IngestServiceImage;
|
import org.sleuthkit.autopsy.ingest.IngestModuleImage;
|
||||||
import org.sleuthkit.datamodel.*;
|
import org.sleuthkit.datamodel.*;
|
||||||
|
|
||||||
abstract public class Extract implements IngestServiceImage{
|
abstract public class Extract implements IngestModuleImage{
|
||||||
|
|
||||||
protected Case currentCase = Case.getCurrentCase(); // get the most updated case
|
protected Case currentCase = Case.getCurrentCase(); // get the most updated case
|
||||||
protected SleuthkitCase tskCase = currentCase.getSleuthkitCase();
|
protected SleuthkitCase tskCase = currentCase.getSleuthkitCase();
|
||||||
|
@ -50,12 +50,10 @@ import org.sleuthkit.autopsy.coreutils.DecodeUtil;
|
|||||||
import org.sleuthkit.autopsy.coreutils.JLNK;
|
import org.sleuthkit.autopsy.coreutils.JLNK;
|
||||||
import org.sleuthkit.autopsy.coreutils.JLnkParser;
|
import org.sleuthkit.autopsy.coreutils.JLnkParser;
|
||||||
import org.sleuthkit.autopsy.datamodel.ContentUtils;
|
import org.sleuthkit.autopsy.datamodel.ContentUtils;
|
||||||
import org.sleuthkit.autopsy.datamodel.DataConversion;
|
|
||||||
import org.sleuthkit.autopsy.datamodel.KeyValue;
|
import org.sleuthkit.autopsy.datamodel.KeyValue;
|
||||||
import org.sleuthkit.autopsy.ingest.IngestImageWorkerController;
|
import org.sleuthkit.autopsy.ingest.IngestImageWorkerController;
|
||||||
import org.sleuthkit.autopsy.ingest.IngestManager;
|
import org.sleuthkit.autopsy.ingest.IngestServices;
|
||||||
import org.sleuthkit.autopsy.ingest.IngestManagerProxy;
|
import org.sleuthkit.autopsy.ingest.ModuleDataEvent;
|
||||||
import org.sleuthkit.autopsy.ingest.ServiceDataEvent;
|
|
||||||
import org.sleuthkit.datamodel.BlackboardArtifact;
|
import org.sleuthkit.datamodel.BlackboardArtifact;
|
||||||
import org.sleuthkit.datamodel.BlackboardArtifact.ARTIFACT_TYPE;
|
import org.sleuthkit.datamodel.BlackboardArtifact.ARTIFACT_TYPE;
|
||||||
import org.sleuthkit.datamodel.BlackboardAttribute;
|
import org.sleuthkit.datamodel.BlackboardAttribute;
|
||||||
@ -64,12 +62,16 @@ import org.sleuthkit.datamodel.Content;
|
|||||||
import org.sleuthkit.datamodel.FsContent;
|
import org.sleuthkit.datamodel.FsContent;
|
||||||
import org.sleuthkit.datamodel.SleuthkitCase;
|
import org.sleuthkit.datamodel.SleuthkitCase;
|
||||||
import org.sleuthkit.autopsy.coreutils.PlatformUtil;
|
import org.sleuthkit.autopsy.coreutils.PlatformUtil;
|
||||||
import org.sleuthkit.autopsy.ingest.IngestServiceImage;
|
import org.sleuthkit.autopsy.ingest.IngestModuleImage;
|
||||||
|
import org.sleuthkit.autopsy.ingest.IngestModuleInit;
|
||||||
import org.sleuthkit.datamodel.*;
|
import org.sleuthkit.datamodel.*;
|
||||||
|
|
||||||
public class ExtractIE extends Extract implements IngestServiceImage {
|
public class ExtractIE extends Extract implements IngestModuleImage {
|
||||||
|
|
||||||
private static final Logger logger = Logger.getLogger(ExtractIE.class.getName());
|
private static final Logger logger = Logger.getLogger(ExtractIE.class.getName());
|
||||||
|
|
||||||
|
private IngestServices services;
|
||||||
|
|
||||||
private String indexDatQueryStr = "select * from tsk_files where name LIKE '%index.dat%'";
|
private String indexDatQueryStr = "select * from tsk_files where name LIKE '%index.dat%'";
|
||||||
private String favoriteQuery = "select * from `tsk_files` where parent_path LIKE '%/Favorites%' and name LIKE '%.url'";
|
private String favoriteQuery = "select * from `tsk_files` where parent_path LIKE '%/Favorites%' and name LIKE '%.url'";
|
||||||
private String cookiesQuery = "select * from `tsk_files` where parent_path LIKE '%/Cookies%' and name LIKE '%.txt'";
|
private String cookiesQuery = "select * from `tsk_files` where parent_path LIKE '%/Cookies%' and name LIKE '%.txt'";
|
||||||
@ -142,7 +144,8 @@ public class ExtractIE extends Extract implements IngestServiceImage {
|
|||||||
bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_PROG_NAME.getTypeID(), "RecentActivity", "Internet Explorer"));
|
bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_PROG_NAME.getTypeID(), "RecentActivity", "Internet Explorer"));
|
||||||
bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DOMAIN.getTypeID(), "RecentActivity", domain));
|
bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DOMAIN.getTypeID(), "RecentActivity", domain));
|
||||||
this.addArtifact(ARTIFACT_TYPE.TSK_WEB_BOOKMARK, Favorite, bbattributes);
|
this.addArtifact(ARTIFACT_TYPE.TSK_WEB_BOOKMARK, Favorite, bbattributes);
|
||||||
IngestManagerProxy.fireServiceDataEvent(new ServiceDataEvent("Recent Activity", BlackboardArtifact.ARTIFACT_TYPE.TSK_WEB_BOOKMARK));
|
|
||||||
|
services.fireModuleDataEvent(new ModuleDataEvent("Recent Activity", BlackboardArtifact.ARTIFACT_TYPE.TSK_WEB_BOOKMARK));
|
||||||
} catch (Exception ex) {
|
} catch (Exception ex) {
|
||||||
logger.log(Level.WARNING, "Error while trying to read into a sqlite db.{0}", ex);
|
logger.log(Level.WARNING, "Error while trying to read into a sqlite db.{0}", ex);
|
||||||
this.addErrorMessage(this.getName() + ": Error while trying to analyze file:" + Favorite.getName());
|
this.addErrorMessage(this.getName() + ": Error while trying to analyze file:" + Favorite.getName());
|
||||||
@ -195,7 +198,7 @@ public class ExtractIE extends Extract implements IngestServiceImage {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
IngestManagerProxy.fireServiceDataEvent(new ServiceDataEvent("Recent Activity", BlackboardArtifact.ARTIFACT_TYPE.TSK_WEB_COOKIE));
|
services.fireModuleDataEvent(new ModuleDataEvent("Recent Activity", BlackboardArtifact.ARTIFACT_TYPE.TSK_WEB_COOKIE));
|
||||||
}
|
}
|
||||||
|
|
||||||
//Recent Documents section
|
//Recent Documents section
|
||||||
@ -225,7 +228,8 @@ public class ExtractIE extends Extract implements IngestServiceImage {
|
|||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
IngestManagerProxy.fireServiceDataEvent(new ServiceDataEvent("Recent Activity", BlackboardArtifact.ARTIFACT_TYPE.TSK_RECENT_OBJECT));
|
|
||||||
|
services.fireModuleDataEvent(new ModuleDataEvent("Recent Activity", BlackboardArtifact.ARTIFACT_TYPE.TSK_RECENT_OBJECT));
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -488,12 +492,12 @@ public class ExtractIE extends Extract implements IngestServiceImage {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
IngestManagerProxy.fireServiceDataEvent(new ServiceDataEvent("Recent Activity", BlackboardArtifact.ARTIFACT_TYPE.TSK_WEB_HISTORY));
|
services.fireModuleDataEvent(new ModuleDataEvent("Recent Activity", BlackboardArtifact.ARTIFACT_TYPE.TSK_WEB_HISTORY));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void init(IngestManagerProxy managerProxy) {
|
public void init(IngestModuleInit initContext) {
|
||||||
throw new UnsupportedOperationException("Not supported yet.");
|
services = IngestServices.getDefault();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -515,8 +519,8 @@ public class ExtractIE extends Extract implements IngestServiceImage {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ServiceType getType() {
|
public ModuleType getType() {
|
||||||
return ServiceType.Image;
|
return ModuleType.Image;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -28,7 +28,6 @@ import java.text.SimpleDateFormat;
|
|||||||
import java.util.*;
|
import java.util.*;
|
||||||
import java.util.logging.Level;
|
import java.util.logging.Level;
|
||||||
import java.util.logging.Logger;
|
import java.util.logging.Logger;
|
||||||
import javax.swing.JPanel;
|
|
||||||
import org.jdom.Document;
|
import org.jdom.Document;
|
||||||
import org.jdom.Element;
|
import org.jdom.Element;
|
||||||
import org.jdom.input.SAXBuilder;
|
import org.jdom.input.SAXBuilder;
|
||||||
@ -36,8 +35,9 @@ import org.openide.modules.InstalledFileLocator;
|
|||||||
import org.sleuthkit.autopsy.casemodule.Case;
|
import org.sleuthkit.autopsy.casemodule.Case;
|
||||||
import org.sleuthkit.autopsy.datamodel.ContentUtils;
|
import org.sleuthkit.autopsy.datamodel.ContentUtils;
|
||||||
import org.sleuthkit.autopsy.ingest.IngestImageWorkerController;
|
import org.sleuthkit.autopsy.ingest.IngestImageWorkerController;
|
||||||
import org.sleuthkit.autopsy.ingest.IngestManagerProxy;
|
import org.sleuthkit.autopsy.ingest.IngestServices;
|
||||||
import org.sleuthkit.autopsy.ingest.IngestServiceImage;
|
import org.sleuthkit.autopsy.ingest.IngestModuleImage;
|
||||||
|
import org.sleuthkit.autopsy.ingest.IngestModuleInit;
|
||||||
import org.sleuthkit.datamodel.BlackboardArtifact.ARTIFACT_TYPE;
|
import org.sleuthkit.datamodel.BlackboardArtifact.ARTIFACT_TYPE;
|
||||||
import org.sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE;
|
import org.sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE;
|
||||||
import org.sleuthkit.datamodel.*;
|
import org.sleuthkit.datamodel.*;
|
||||||
@ -45,12 +45,13 @@ import org.sleuthkit.datamodel.*;
|
|||||||
/**
|
/**
|
||||||
* Extracting windows registry data using regripper
|
* Extracting windows registry data using regripper
|
||||||
*/
|
*/
|
||||||
public class ExtractRegistry extends Extract implements IngestServiceImage {
|
public class ExtractRegistry extends Extract implements IngestModuleImage {
|
||||||
|
|
||||||
public Logger logger = Logger.getLogger(this.getClass().getName());
|
public Logger logger = Logger.getLogger(this.getClass().getName());
|
||||||
private String RR_PATH;
|
private String RR_PATH;
|
||||||
boolean rrFound = false;
|
boolean rrFound = false;
|
||||||
private int sysid;
|
private int sysid;
|
||||||
|
private IngestServices services;
|
||||||
|
|
||||||
ExtractRegistry() {
|
ExtractRegistry() {
|
||||||
final File rrRoot = InstalledFileLocator.getDefault().locate("rr", ExtractRegistry.class.getPackage().getName(), false);
|
final File rrRoot = InstalledFileLocator.getDefault().locate("rr", ExtractRegistry.class.getPackage().getName(), false);
|
||||||
@ -328,8 +329,8 @@ public class ExtractRegistry extends Extract implements IngestServiceImage {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void init(IngestManagerProxy managerProxy) {
|
public void init(IngestModuleInit initContext) {
|
||||||
throw new UnsupportedOperationException("Not supported yet.");
|
services = IngestServices.getDefault();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -355,8 +356,8 @@ public class ExtractRegistry extends Extract implements IngestServiceImage {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ServiceType getType() {
|
public ModuleType getType() {
|
||||||
return ServiceType.Image;
|
return ModuleType.Image;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -27,14 +27,13 @@ import java.util.Collection;
|
|||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.logging.Level;
|
import java.util.logging.Level;
|
||||||
import javax.swing.JPanel;
|
|
||||||
import org.sleuthkit.autopsy.coreutils.DecodeUtil;
|
import org.sleuthkit.autopsy.coreutils.DecodeUtil;
|
||||||
import org.sleuthkit.autopsy.datamodel.ContentUtils;
|
import org.sleuthkit.autopsy.datamodel.ContentUtils;
|
||||||
import org.sleuthkit.autopsy.ingest.IngestImageWorkerController;
|
import org.sleuthkit.autopsy.ingest.IngestImageWorkerController;
|
||||||
import org.sleuthkit.autopsy.ingest.IngestManager;
|
import org.sleuthkit.autopsy.ingest.IngestServices;
|
||||||
import org.sleuthkit.autopsy.ingest.IngestManagerProxy;
|
import org.sleuthkit.autopsy.ingest.IngestModuleImage;
|
||||||
import org.sleuthkit.autopsy.ingest.IngestServiceImage;
|
import org.sleuthkit.autopsy.ingest.IngestModuleInit;
|
||||||
import org.sleuthkit.autopsy.ingest.ServiceDataEvent;
|
import org.sleuthkit.autopsy.ingest.ModuleDataEvent;
|
||||||
import org.sleuthkit.datamodel.BlackboardArtifact;
|
import org.sleuthkit.datamodel.BlackboardArtifact;
|
||||||
import org.sleuthkit.datamodel.BlackboardArtifact.ARTIFACT_TYPE;
|
import org.sleuthkit.datamodel.BlackboardArtifact.ARTIFACT_TYPE;
|
||||||
import org.sleuthkit.datamodel.BlackboardAttribute;
|
import org.sleuthkit.datamodel.BlackboardAttribute;
|
||||||
@ -43,10 +42,10 @@ import org.sleuthkit.datamodel.FsContent;
|
|||||||
import org.sleuthkit.datamodel.Image;
|
import org.sleuthkit.datamodel.Image;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
* Firefox recent activity extraction
|
||||||
* @author Alex
|
|
||||||
*/
|
*/
|
||||||
public class Firefox extends Extract implements IngestServiceImage {
|
public class Firefox extends Extract implements IngestModuleImage {
|
||||||
|
|
||||||
|
|
||||||
private static final String ffquery = "SELECT moz_historyvisits.id,url,title,visit_count,(visit_date/1000000) as visit_date,from_visit,(SELECT url FROM moz_places WHERE id=moz_historyvisits.from_visit) as ref FROM moz_places, moz_historyvisits WHERE moz_places.id = moz_historyvisits.place_id AND hidden = 0";
|
private static final String ffquery = "SELECT moz_historyvisits.id,url,title,visit_count,(visit_date/1000000) as visit_date,from_visit,(SELECT url FROM moz_places WHERE id=moz_historyvisits.from_visit) as ref FROM moz_places, moz_historyvisits WHERE moz_places.id = moz_historyvisits.place_id AND hidden = 0";
|
||||||
private static final String ffcookiequery = "SELECT name,value,host,expiry,(lastAccessed/1000000) as lastAccessed,(creationTime/1000000) as creationTime FROM moz_cookies";
|
private static final String ffcookiequery = "SELECT name,value,host,expiry,(lastAccessed/1000000) as lastAccessed,(creationTime/1000000) as creationTime FROM moz_cookies";
|
||||||
@ -55,6 +54,8 @@ public class Firefox extends Extract implements IngestServiceImage {
|
|||||||
private static final String ffdownloadquery = "select target, source,(startTime/1000000) as startTime, maxBytes from moz_downloads";
|
private static final String ffdownloadquery = "select target, source,(startTime/1000000) as startTime, maxBytes from moz_downloads";
|
||||||
public int FireFoxCount = 0;
|
public int FireFoxCount = 0;
|
||||||
|
|
||||||
|
private IngestServices services;
|
||||||
|
|
||||||
public Firefox() {
|
public Firefox() {
|
||||||
moduleName = "FireFox";
|
moduleName = "FireFox";
|
||||||
}
|
}
|
||||||
@ -108,7 +109,8 @@ public class Firefox extends Extract implements IngestServiceImage {
|
|||||||
j++;
|
j++;
|
||||||
dbFile.delete();
|
dbFile.delete();
|
||||||
}
|
}
|
||||||
IngestManagerProxy.fireServiceDataEvent(new ServiceDataEvent("Recent Activity", BlackboardArtifact.ARTIFACT_TYPE.TSK_WEB_HISTORY));
|
|
||||||
|
services.fireModuleDataEvent(new ModuleDataEvent("Recent Activity", BlackboardArtifact.ARTIFACT_TYPE.TSK_WEB_HISTORY));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -151,7 +153,8 @@ public class Firefox extends Extract implements IngestServiceImage {
|
|||||||
j++;
|
j++;
|
||||||
dbFile.delete();
|
dbFile.delete();
|
||||||
}
|
}
|
||||||
IngestManagerProxy.fireServiceDataEvent(new ServiceDataEvent("Recent Activity", BlackboardArtifact.ARTIFACT_TYPE.TSK_WEB_BOOKMARK));
|
|
||||||
|
services.fireModuleDataEvent(new ModuleDataEvent("Recent Activity", BlackboardArtifact.ARTIFACT_TYPE.TSK_WEB_BOOKMARK));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -211,7 +214,8 @@ public class Firefox extends Extract implements IngestServiceImage {
|
|||||||
j++;
|
j++;
|
||||||
dbFile.delete();
|
dbFile.delete();
|
||||||
}
|
}
|
||||||
IngestManagerProxy.fireServiceDataEvent(new ServiceDataEvent("Recent Activity", BlackboardArtifact.ARTIFACT_TYPE.TSK_WEB_COOKIE));
|
|
||||||
|
services.fireModuleDataEvent(new ModuleDataEvent("Recent Activity", BlackboardArtifact.ARTIFACT_TYPE.TSK_WEB_COOKIE));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -259,13 +263,14 @@ public class Firefox extends Extract implements IngestServiceImage {
|
|||||||
j++;
|
j++;
|
||||||
dbFile.delete();
|
dbFile.delete();
|
||||||
}
|
}
|
||||||
IngestManagerProxy.fireServiceDataEvent(new ServiceDataEvent("Recent Activity", BlackboardArtifact.ARTIFACT_TYPE.TSK_WEB_DOWNLOAD));
|
|
||||||
|
services.fireModuleDataEvent(new ModuleDataEvent("Recent Activity", BlackboardArtifact.ARTIFACT_TYPE.TSK_WEB_DOWNLOAD));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void init(IngestManagerProxy managerProxy) {
|
public void init(IngestModuleInit initContext) {
|
||||||
throw new UnsupportedOperationException("Not supported yet.");
|
services = IngestServices.getDefault();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -284,8 +289,8 @@ public class Firefox extends Extract implements IngestServiceImage {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ServiceType getType() {
|
public ModuleType getType() {
|
||||||
return ServiceType.Image;
|
return ModuleType.Image;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -25,21 +25,22 @@ import java.util.List;
|
|||||||
import java.util.logging.Level;
|
import java.util.logging.Level;
|
||||||
import java.util.logging.Logger;
|
import java.util.logging.Logger;
|
||||||
import org.sleuthkit.autopsy.ingest.IngestImageWorkerController;
|
import org.sleuthkit.autopsy.ingest.IngestImageWorkerController;
|
||||||
import org.sleuthkit.autopsy.ingest.IngestManagerProxy;
|
import org.sleuthkit.autopsy.ingest.IngestServices;
|
||||||
import org.sleuthkit.autopsy.ingest.IngestMessage;
|
import org.sleuthkit.autopsy.ingest.IngestMessage;
|
||||||
import org.sleuthkit.autopsy.ingest.IngestMessage.MessageType;
|
import org.sleuthkit.autopsy.ingest.IngestMessage.MessageType;
|
||||||
import org.sleuthkit.autopsy.ingest.IngestServiceImage;
|
import org.sleuthkit.autopsy.ingest.IngestModuleImage;
|
||||||
|
import org.sleuthkit.autopsy.ingest.IngestModuleInit;
|
||||||
import org.sleuthkit.datamodel.Image;
|
import org.sleuthkit.datamodel.Image;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Recent activity image ingest service
|
* Recent activity image ingest module
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
public final class RAImageIngestService implements IngestServiceImage {
|
public final class RAImageIngestModule implements IngestModuleImage {
|
||||||
|
|
||||||
private static final Logger logger = Logger.getLogger(RAImageIngestService.class.getName());
|
private static final Logger logger = Logger.getLogger(RAImageIngestModule.class.getName());
|
||||||
private static RAImageIngestService defaultInstance = null;
|
private static RAImageIngestModule defaultInstance = null;
|
||||||
private IngestManagerProxy managerProxy;
|
private IngestServices services;
|
||||||
private static int messageId = 0;
|
private static int messageId = 0;
|
||||||
private ArrayList<String> errors = new ArrayList<String>();
|
private ArrayList<String> errors = new ArrayList<String>();
|
||||||
private StringBuilder subCompleted = new StringBuilder();
|
private StringBuilder subCompleted = new StringBuilder();
|
||||||
@ -51,13 +52,13 @@ public final class RAImageIngestService implements IngestServiceImage {
|
|||||||
|
|
||||||
//public constructor is required
|
//public constructor is required
|
||||||
//as multiple instances are created for processing multiple images simultenously
|
//as multiple instances are created for processing multiple images simultenously
|
||||||
public RAImageIngestService() {
|
public RAImageIngestModule() {
|
||||||
}
|
}
|
||||||
|
|
||||||
//default instance used for service registration
|
//default instance used for module registration
|
||||||
public static synchronized RAImageIngestService getDefault() {
|
public static synchronized RAImageIngestModule getDefault() {
|
||||||
if (defaultInstance == null) {
|
if (defaultInstance == null) {
|
||||||
defaultInstance = new RAImageIngestService();
|
defaultInstance = new RAImageIngestModule();
|
||||||
}
|
}
|
||||||
return defaultInstance;
|
return defaultInstance;
|
||||||
}
|
}
|
||||||
@ -71,7 +72,7 @@ public final class RAImageIngestService implements IngestServiceImage {
|
|||||||
modules.add(chre);
|
modules.add(chre);
|
||||||
modules.add(eere);
|
modules.add(eere);
|
||||||
modules.add(usq);
|
modules.add(usq);
|
||||||
managerProxy.postMessage(IngestMessage.createMessage(++messageId, MessageType.INFO, this, "Started " + image.getName()));
|
services.postMessage(IngestMessage.createMessage(++messageId, MessageType.INFO, this, "Started " + image.getName()));
|
||||||
controller.switchToDeterminate(modules.size());
|
controller.switchToDeterminate(modules.size());
|
||||||
controller.progress(0);
|
controller.progress(0);
|
||||||
|
|
||||||
@ -101,7 +102,7 @@ public final class RAImageIngestService implements IngestServiceImage {
|
|||||||
for (String msg : errors) {
|
for (String msg : errors) {
|
||||||
i++;
|
i++;
|
||||||
final IngestMessage error = IngestMessage.createMessage(++messageId, MessageType.INFO, this, msg + "<br>");
|
final IngestMessage error = IngestMessage.createMessage(++messageId, MessageType.INFO, this, msg + "<br>");
|
||||||
managerProxy.postMessage(error);
|
services.postMessage(error);
|
||||||
}
|
}
|
||||||
errorsFound = i + " errors found!";
|
errorsFound = i + " errors found!";
|
||||||
}else
|
}else
|
||||||
@ -110,9 +111,9 @@ public final class RAImageIngestService implements IngestServiceImage {
|
|||||||
errorsFound = "No errors reported";
|
errorsFound = "No errors reported";
|
||||||
}
|
}
|
||||||
final IngestMessage msg = IngestMessage.createMessage(++messageId, MessageType.INFO, this, "Completed - " + errorsFound, errorMessage.toString());
|
final IngestMessage msg = IngestMessage.createMessage(++messageId, MessageType.INFO, this, "Completed - " + errorsFound, errorMessage.toString());
|
||||||
managerProxy.postMessage(msg);
|
services.postMessage(msg);
|
||||||
|
|
||||||
//service specific cleanup due to completion here
|
//module specific cleanup due to completion here
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -126,20 +127,29 @@ public final class RAImageIngestService implements IngestServiceImage {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void init(IngestManagerProxy managerProxy) {
|
public void init(IngestModuleInit initContext) {
|
||||||
logger.log(Level.INFO, "init() " + this.toString());
|
logger.log(Level.INFO, "init() " + this.toString());
|
||||||
this.managerProxy = managerProxy;
|
services = IngestServices.getDefault();
|
||||||
this.eere = new ExtractIE();
|
|
||||||
this.chre = new Chrome();
|
|
||||||
this.eree = new ExtractRegistry();
|
|
||||||
this.ffre = new Firefox();
|
|
||||||
this.usq = new SearchEngineURLQueryAnalyzer();
|
|
||||||
|
|
||||||
|
eere = new ExtractIE();
|
||||||
|
eere.init(initContext);
|
||||||
|
|
||||||
|
chre = new Chrome();
|
||||||
|
chre.init(initContext);
|
||||||
|
|
||||||
|
eree = new ExtractRegistry();
|
||||||
|
eree.init(initContext);
|
||||||
|
|
||||||
|
ffre = new Firefox();
|
||||||
|
ffre.init(initContext);
|
||||||
|
|
||||||
|
usq = new SearchEngineURLQueryAnalyzer();
|
||||||
|
usq.init(initContext);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void stop() {
|
public void stop() {
|
||||||
logger.log(Level.INFO, "RAImageIngetService::stop()");
|
logger.log(Level.INFO, "RAImageIngetModule::stop()");
|
||||||
//Order Matters
|
//Order Matters
|
||||||
//ExtractRegistry stop
|
//ExtractRegistry stop
|
||||||
this.eree.stop();
|
this.eree.stop();
|
||||||
@ -149,8 +159,8 @@ public final class RAImageIngestService implements IngestServiceImage {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ServiceType getType() {
|
public ModuleType getType() {
|
||||||
return ServiceType.Image;
|
return ModuleType.Image;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
@ -24,12 +24,12 @@ import java.net.URLDecoder;
|
|||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.logging.Level;
|
import java.util.logging.Level;
|
||||||
import java.util.logging.Logger;
|
|
||||||
import javax.swing.JPanel;
|
import javax.swing.JPanel;
|
||||||
import org.sleuthkit.autopsy.ingest.IngestImageWorkerController;
|
import org.sleuthkit.autopsy.ingest.IngestImageWorkerController;
|
||||||
import org.sleuthkit.autopsy.ingest.IngestManagerProxy;
|
import org.sleuthkit.autopsy.ingest.IngestServices;
|
||||||
import org.sleuthkit.autopsy.ingest.IngestServiceImage;
|
import org.sleuthkit.autopsy.ingest.IngestModuleImage;
|
||||||
import org.sleuthkit.autopsy.ingest.ServiceDataEvent;
|
import org.sleuthkit.autopsy.ingest.IngestModuleInit;
|
||||||
|
import org.sleuthkit.autopsy.ingest.ModuleDataEvent;
|
||||||
import org.sleuthkit.datamodel.BlackboardArtifact;
|
import org.sleuthkit.datamodel.BlackboardArtifact;
|
||||||
import org.sleuthkit.datamodel.BlackboardArtifact.ARTIFACT_TYPE;
|
import org.sleuthkit.datamodel.BlackboardArtifact.ARTIFACT_TYPE;
|
||||||
import org.sleuthkit.datamodel.BlackboardAttribute;
|
import org.sleuthkit.datamodel.BlackboardAttribute;
|
||||||
@ -47,7 +47,9 @@ import org.sleuthkit.datamodel.Image;
|
|||||||
* enum, getSearchEngine(), extractSearchEngineQuery()
|
* enum, getSearchEngine(), extractSearchEngineQuery()
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
public class SearchEngineURLQueryAnalyzer extends Extract implements IngestServiceImage {
|
public class SearchEngineURLQueryAnalyzer extends Extract implements IngestModuleImage {
|
||||||
|
|
||||||
|
private IngestServices services;
|
||||||
|
|
||||||
static final String MODULE_NAME = "Search Engine Query Analyzer";
|
static final String MODULE_NAME = "Search Engine Query Analyzer";
|
||||||
|
|
||||||
@ -336,7 +338,7 @@ public class SearchEngineURLQueryAnalyzer extends Extract implements IngestServi
|
|||||||
logger.log(Level.SEVERE, "Error while add artifact.", e + " from " + fs.toString());
|
logger.log(Level.SEVERE, "Error while add artifact.", e + " from " + fs.toString());
|
||||||
this.addErrorMessage(this.getName() + ": Error while adding artifact");
|
this.addErrorMessage(this.getName() + ": Error while adding artifact");
|
||||||
}
|
}
|
||||||
IngestManagerProxy.fireServiceDataEvent(new ServiceDataEvent("RecentActivity", BlackboardArtifact.ARTIFACT_TYPE.TSK_WEB_SEARCH_QUERY));
|
services.fireModuleDataEvent(new ModuleDataEvent("RecentActivity", BlackboardArtifact.ARTIFACT_TYPE.TSK_WEB_SEARCH_QUERY));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -368,7 +370,8 @@ public class SearchEngineURLQueryAnalyzer extends Extract implements IngestServi
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void init(IngestManagerProxy managerProxy) {
|
public void init(IngestModuleInit initContext) {
|
||||||
|
services = IngestServices.getDefault();
|
||||||
logger.info("running init()");
|
logger.info("running init()");
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -404,8 +407,8 @@ public class SearchEngineURLQueryAnalyzer extends Extract implements IngestServi
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ServiceType getType() {
|
public ModuleType getType() {
|
||||||
return ServiceType.Image;
|
return ModuleType.Image;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -2,9 +2,9 @@
|
|||||||
<!DOCTYPE filesystem PUBLIC "-//NetBeans//DTD Filesystem 1.2//EN" "http://www.netbeans.org/dtds/filesystem-1_2.dtd">
|
<!DOCTYPE filesystem PUBLIC "-//NetBeans//DTD Filesystem 1.2//EN" "http://www.netbeans.org/dtds/filesystem-1_2.dtd">
|
||||||
<filesystem>
|
<filesystem>
|
||||||
<folder name="Services">
|
<folder name="Services">
|
||||||
<file name="org-sleuthkit-autopsy-recentactivity-RAImageIngestService.instance">
|
<file name="org-sleuthkit-autopsy-recentactivity-RAImageIngestModule.instance">
|
||||||
<attr name="instanceOf" stringvalue="org.sleuthkit.autopsy.ingest.IngestServiceImage"/>
|
<attr name="instanceOf" stringvalue="org.sleuthkit.autopsy.ingest.IngestModuleImage"/>
|
||||||
<attr name="instanceCreate" methodvalue="org.sleuthkit.autopsy.recentactivity.RAImageIngestService.getDefault"/>
|
<attr name="instanceCreate" methodvalue="org.sleuthkit.autopsy.recentactivity.RAImageIngestModule.getDefault"/>
|
||||||
<attr name="position" intvalue="110"/>
|
<attr name="position" intvalue="110"/>
|
||||||
</file>
|
</file>
|
||||||
</folder>
|
</folder>
|
||||||
|
@ -200,7 +200,7 @@ public class ReportHTML implements ReportModule {
|
|||||||
if (IngestManager.getDefault().isIngestRunning()) {
|
if (IngestManager.getDefault().isIngestRunning()) {
|
||||||
formatted_Report.append(ingestwarning);
|
formatted_Report.append(ingestwarning);
|
||||||
}
|
}
|
||||||
else if (IngestManager.getDefault().areServicesRunning()) {
|
else if (IngestManager.getDefault().areModulesRunning()) {
|
||||||
formatted_Report.append(ingestwarning);
|
formatted_Report.append(ingestwarning);
|
||||||
}
|
}
|
||||||
formatted_Report.append("<h2>Case Summary</h2><p>HTML Report Generated by <strong>Autopsy 3</strong> on ").append(datetime).append("<ul>");
|
formatted_Report.append("<h2>Case Summary</h2><p>HTML Report Generated by <strong>Autopsy 3</strong> on ").append(datetime).append("<ul>");
|
||||||
|
@ -225,7 +225,7 @@ public class RegressionTest extends TestCase{
|
|||||||
}
|
}
|
||||||
new Timeout("pausing", 15000).sleep(); // give it a second (or fifteen) to process
|
new Timeout("pausing", 15000).sleep(); // give it a second (or fifteen) to process
|
||||||
boolean sleep = true;
|
boolean sleep = true;
|
||||||
while (man.areServicesRunning()) {
|
while (man.areModulesRunning()) {
|
||||||
new Timeout("pausing", 5000).sleep(); // give it a second (or five) to process
|
new Timeout("pausing", 5000).sleep(); // give it a second (or five) to process
|
||||||
}
|
}
|
||||||
logger.info("Ingest (including enqueue) took " + (System.currentTimeMillis()-start) + "ms");
|
logger.info("Ingest (including enqueue) took " + (System.currentTimeMillis()-start) + "ms");
|
||||||
|
@ -50,7 +50,7 @@ When an item is selected from the result viewer area, it is passed to the bottom
|
|||||||
|
|
||||||
The component is by default registered with the ingest manager as an ingest event listener.
|
The component is by default registered with the ingest manager as an ingest event listener.
|
||||||
The viewer first loads all the viewer-supported data currently in the blackboard when Autopsy starts.
|
The viewer first loads all the viewer-supported data currently in the blackboard when Autopsy starts.
|
||||||
During the ingest process the viewer receives events from ingest services
|
During the ingest process the viewer receives events from ingest modules
|
||||||
(relayed by ingest manager) and it selectively refreshes parts of the tree providing real-time updates to the user.
|
(relayed by ingest manager) and it selectively refreshes parts of the tree providing real-time updates to the user.
|
||||||
When ingest is completed, the viewer responds to the final ingest data event generated by the ingest manager,
|
When ingest is completed, the viewer responds to the final ingest data event generated by the ingest manager,
|
||||||
and performs a final refresh of all viewer-supported data in the blackboard.
|
and performs a final refresh of all viewer-supported data in the blackboard.
|
||||||
|
@ -124,7 +124,7 @@ public class ThunderbirdEmailParser {
|
|||||||
ftime = ftime / 1000;
|
ftime = ftime / 1000;
|
||||||
dates = ftime;
|
dates = ftime;
|
||||||
} catch (ParseException ex) {
|
} catch (ParseException ex) {
|
||||||
Logger.getLogger(ThunderbirdMboxFileIngestService.class.getName()).log(Level.WARNING, null, ex);
|
Logger.getLogger(ThunderbirdMboxFileIngestModule.class.getName()).log(Level.WARNING, null, ex);
|
||||||
}
|
}
|
||||||
|
|
||||||
return dates;
|
return dates;
|
||||||
|
@ -33,13 +33,12 @@ import java.util.logging.Level;
|
|||||||
import java.util.logging.Logger;
|
import java.util.logging.Logger;
|
||||||
import org.apache.tika.exception.TikaException;
|
import org.apache.tika.exception.TikaException;
|
||||||
import org.apache.tika.metadata.Metadata;
|
import org.apache.tika.metadata.Metadata;
|
||||||
import org.sleuthkit.autopsy.ingest.IngestManager;
|
import org.sleuthkit.autopsy.ingest.IngestServices;
|
||||||
import org.sleuthkit.autopsy.ingest.IngestManagerProxy;
|
|
||||||
import org.sleuthkit.autopsy.ingest.IngestMessage;
|
import org.sleuthkit.autopsy.ingest.IngestMessage;
|
||||||
import org.sleuthkit.autopsy.ingest.IngestMessage.MessageType;
|
import org.sleuthkit.autopsy.ingest.IngestMessage.MessageType;
|
||||||
import org.sleuthkit.autopsy.ingest.IngestServiceAbstract.*;
|
import org.sleuthkit.autopsy.ingest.IngestModuleAbstract.*;
|
||||||
import org.sleuthkit.autopsy.ingest.IngestServiceAbstractFile;
|
import org.sleuthkit.autopsy.ingest.IngestModuleAbstractFile;
|
||||||
import org.sleuthkit.autopsy.ingest.ServiceDataEvent;
|
import org.sleuthkit.autopsy.ingest.ModuleDataEvent;
|
||||||
import org.sleuthkit.datamodel.AbstractFile;
|
import org.sleuthkit.datamodel.AbstractFile;
|
||||||
import org.sleuthkit.datamodel.BlackboardArtifact;
|
import org.sleuthkit.datamodel.BlackboardArtifact;
|
||||||
import org.sleuthkit.datamodel.BlackboardAttribute;
|
import org.sleuthkit.datamodel.BlackboardAttribute;
|
||||||
@ -51,55 +50,60 @@ import org.xml.sax.SAXException;
|
|||||||
import org.apache.commons.lang.StringEscapeUtils;
|
import org.apache.commons.lang.StringEscapeUtils;
|
||||||
import org.sleuthkit.autopsy.casemodule.Case;
|
import org.sleuthkit.autopsy.casemodule.Case;
|
||||||
import org.sleuthkit.autopsy.datamodel.ContentUtils;
|
import org.sleuthkit.autopsy.datamodel.ContentUtils;
|
||||||
|
import org.sleuthkit.autopsy.ingest.IngestModuleInit;
|
||||||
import org.sleuthkit.datamodel.Content;
|
import org.sleuthkit.datamodel.Content;
|
||||||
|
import org.sleuthkit.datamodel.ContentVisitor;
|
||||||
import org.sleuthkit.datamodel.SleuthkitCase;
|
import org.sleuthkit.datamodel.SleuthkitCase;
|
||||||
|
import org.sleuthkit.datamodel.TskData;
|
||||||
|
|
||||||
public class ThunderbirdMboxFileIngestService implements IngestServiceAbstractFile {
|
|
||||||
|
|
||||||
private static final Logger logger = Logger.getLogger(ThunderbirdMboxFileIngestService.class.getName());
|
public class ThunderbirdMboxFileIngestModule implements IngestModuleAbstractFile {
|
||||||
private static ThunderbirdMboxFileIngestService instance = null;
|
|
||||||
private IngestManagerProxy managerProxy;
|
private static final Logger logger = Logger.getLogger(ThunderbirdMboxFileIngestModule.class.getName());
|
||||||
|
private static ThunderbirdMboxFileIngestModule instance = null;
|
||||||
|
private IngestServices services;
|
||||||
private static int messageId = 0;
|
private static int messageId = 0;
|
||||||
private static final String classname = "Thunderbird Parser";
|
private static final String classname = "Thunderbird Parser";
|
||||||
private final String hashDBServiceName = "Hash Lookup";
|
private final String hashDBModuleName = "Hash Lookup";
|
||||||
|
private final GetIsFileKnownVisitor getIsFileKnown = new GetIsFileKnownVisitor();
|
||||||
|
|
||||||
public static synchronized ThunderbirdMboxFileIngestService getDefault() {
|
public static synchronized ThunderbirdMboxFileIngestModule getDefault() {
|
||||||
if (instance == null) {
|
if (instance == null) {
|
||||||
instance = new ThunderbirdMboxFileIngestService();
|
instance = new ThunderbirdMboxFileIngestModule();
|
||||||
}
|
}
|
||||||
return instance;
|
return instance;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ProcessResult process(AbstractFile fsContent) {
|
public ProcessResult process(AbstractFile abstractFile) {
|
||||||
ThunderbirdEmailParser mbox = new ThunderbirdEmailParser();
|
ThunderbirdEmailParser mbox = new ThunderbirdEmailParser();
|
||||||
boolean isMbox = false;
|
boolean isMbox = false;
|
||||||
|
|
||||||
IngestServiceAbstractFile.ProcessResult hashDBResult =
|
IngestModuleAbstractFile.ProcessResult hashDBResult =
|
||||||
managerProxy.getAbstractFileServiceResult(hashDBServiceName);
|
services.getAbstractFileModuleResult(hashDBModuleName);
|
||||||
|
|
||||||
if (hashDBResult == IngestServiceAbstractFile.ProcessResult.COND_STOP) {
|
if (abstractFile.accept(getIsFileKnown) == true) {
|
||||||
return ProcessResult.OK; //file is known, stop processing it
|
return ProcessResult.OK; //file is known, stop processing it
|
||||||
} else if (hashDBResult == IngestServiceAbstractFile.ProcessResult.ERROR) {
|
} else if (hashDBResult == IngestModuleAbstractFile.ProcessResult.ERROR) {
|
||||||
return ProcessResult.ERROR; //file has read error, stop processing it
|
return ProcessResult.ERROR; //file has read error, stop processing it
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
byte[] t = new byte[64];
|
byte[] t = new byte[64];
|
||||||
if(fsContent.getSize() > 64) {
|
if(abstractFile.getSize() > 64) {
|
||||||
int byteRead = fsContent.read(t, 0, 64);
|
int byteRead = abstractFile.read(t, 0, 64);
|
||||||
isMbox = mbox.isValidMimeTypeMbox(t);
|
isMbox = mbox.isValidMimeTypeMbox(t);
|
||||||
}
|
}
|
||||||
} catch (TskException ex) {
|
} catch (TskException ex) {
|
||||||
Logger.getLogger(ThunderbirdMboxFileIngestService.class.getName()).log(Level.WARNING, null, ex);
|
Logger.getLogger(ThunderbirdMboxFileIngestModule.class.getName()).log(Level.WARNING, null, ex);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
if (isMbox) {
|
if (isMbox) {
|
||||||
managerProxy.postMessage(IngestMessage.createMessage(++messageId, MessageType.INFO, this, "Processing " + fsContent.getName()));
|
services.postMessage(IngestMessage.createMessage(++messageId, MessageType.INFO, this, "Processing " + abstractFile.getName()));
|
||||||
String mboxName = fsContent.getName();
|
String mboxName = abstractFile.getName();
|
||||||
String msfName = mboxName + ".msf";
|
String msfName = mboxName + ".msf";
|
||||||
Long mboxId = fsContent.getId();
|
Long mboxId = abstractFile.getId();
|
||||||
String mboxPath = "";
|
String mboxPath = "";
|
||||||
Long msfId = 0L;
|
Long msfId = 0L;
|
||||||
Case currentCase = Case.getCurrentCase(); // get the most updated case
|
Case currentCase = Case.getCurrentCase(); // get the most updated case
|
||||||
@ -133,7 +137,7 @@ public class ThunderbirdMboxFileIngestService implements IngestServiceAbstractFi
|
|||||||
Content msfContent = tskCase.getContentById(msfId);
|
Content msfContent = tskCase.getContentById(msfId);
|
||||||
ContentUtils.writeToFile(msfContent, new File(currentCase.getTempDirectory() + File.separator + msfName));
|
ContentUtils.writeToFile(msfContent, new File(currentCase.getTempDirectory() + File.separator + msfName));
|
||||||
} catch (IOException ex) {
|
} catch (IOException ex) {
|
||||||
Logger.getLogger(ThunderbirdMboxFileIngestService.class.getName()).log(Level.WARNING, null, ex);
|
Logger.getLogger(ThunderbirdMboxFileIngestModule.class.getName()).log(Level.WARNING, null, ex);
|
||||||
} catch (TskCoreException ex) {
|
} catch (TskCoreException ex) {
|
||||||
logger.log(Level.WARNING, "Unable to obtain msf file for mbox parsing:" + this.getClass().getName(), ex);
|
logger.log(Level.WARNING, "Unable to obtain msf file for mbox parsing:" + this.getClass().getName(), ex);
|
||||||
}
|
}
|
||||||
@ -159,7 +163,7 @@ public class ThunderbirdMboxFileIngestService implements IngestServiceAbstractFi
|
|||||||
// try {
|
// try {
|
||||||
// reader = new FileReader(currentCase.getTempDirectory() + File.separator + msfName);
|
// reader = new FileReader(currentCase.getTempDirectory() + File.separator + msfName);
|
||||||
// } catch (FileNotFoundException ex) {
|
// } catch (FileNotFoundException ex) {
|
||||||
// Logger.getLogger(ThunderbirdMboxFileIngestService.class.getName()).log(Level.WARNING, null, ex);
|
// Logger.getLogger(ThunderbirdMboxFileIngestModule.class.getName()).log(Level.WARNING, null, ex);
|
||||||
// }
|
// }
|
||||||
// MorkDocument morkDocument = new MorkDocument(reader);
|
// MorkDocument morkDocument = new MorkDocument(reader);
|
||||||
// List<Dict> dicts = morkDocument.getDicts();
|
// List<Dict> dicts = morkDocument.getDicts();
|
||||||
@ -177,7 +181,7 @@ public class ThunderbirdMboxFileIngestService implements IngestServiceAbstractFi
|
|||||||
String cc = "";
|
String cc = "";
|
||||||
String bcc = "";
|
String bcc = "";
|
||||||
try {
|
try {
|
||||||
ReadContentInputStream contentStream = new ReadContentInputStream(fsContent);
|
ReadContentInputStream contentStream = new ReadContentInputStream(abstractFile);
|
||||||
mbox.parse(contentStream);
|
mbox.parse(contentStream);
|
||||||
HashMap<String, Map<String, String>> emailMap = new HashMap<String, Map<String, String>>();
|
HashMap<String, Map<String, String>> emailMap = new HashMap<String, Map<String, String>>();
|
||||||
emailMap = mbox.getAllEmails();
|
emailMap = mbox.getAllEmails();
|
||||||
@ -211,21 +215,21 @@ public class ThunderbirdMboxFileIngestService implements IngestServiceAbstractFi
|
|||||||
bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_PATH.getTypeID(), classname, folderPath));
|
bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_PATH.getTypeID(), classname, folderPath));
|
||||||
BlackboardArtifact bbart;
|
BlackboardArtifact bbart;
|
||||||
try {
|
try {
|
||||||
bbart = fsContent.newArtifact(BlackboardArtifact.ARTIFACT_TYPE.TSK_EMAIL_MSG);
|
bbart = abstractFile.newArtifact(BlackboardArtifact.ARTIFACT_TYPE.TSK_EMAIL_MSG);
|
||||||
bbart.addAttributes(bbattributes);
|
bbart.addAttributes(bbattributes);
|
||||||
} catch (TskCoreException ex) {
|
} catch (TskCoreException ex) {
|
||||||
Logger.getLogger(ThunderbirdMboxFileIngestService.class.getName()).log(Level.WARNING, null, ex);
|
Logger.getLogger(ThunderbirdMboxFileIngestModule.class.getName()).log(Level.WARNING, null, ex);
|
||||||
}
|
}
|
||||||
IngestManagerProxy.fireServiceDataEvent(new ServiceDataEvent(classname, BlackboardArtifact.ARTIFACT_TYPE.TSK_EMAIL_MSG));
|
services.fireModuleDataEvent(new ModuleDataEvent(classname, BlackboardArtifact.ARTIFACT_TYPE.TSK_EMAIL_MSG));
|
||||||
}
|
}
|
||||||
} catch (FileNotFoundException ex) {
|
} catch (FileNotFoundException ex) {
|
||||||
Logger.getLogger(ThunderbirdMboxFileIngestService.class.getName()).log(Level.WARNING, null, ex);
|
Logger.getLogger(ThunderbirdMboxFileIngestModule.class.getName()).log(Level.WARNING, null, ex);
|
||||||
} catch (IOException ex) {
|
} catch (IOException ex) {
|
||||||
Logger.getLogger(ThunderbirdMboxFileIngestService.class.getName()).log(Level.WARNING, null, ex);
|
Logger.getLogger(ThunderbirdMboxFileIngestModule.class.getName()).log(Level.WARNING, null, ex);
|
||||||
} catch (SAXException ex) {
|
} catch (SAXException ex) {
|
||||||
Logger.getLogger(ThunderbirdMboxFileIngestService.class.getName()).log(Level.WARNING, null, ex);
|
Logger.getLogger(ThunderbirdMboxFileIngestModule.class.getName()).log(Level.WARNING, null, ex);
|
||||||
} catch (TikaException ex) {
|
} catch (TikaException ex) {
|
||||||
Logger.getLogger(ThunderbirdMboxFileIngestService.class.getName()).log(Level.WARNING, null, ex);
|
Logger.getLogger(ThunderbirdMboxFileIngestModule.class.getName()).log(Level.WARNING, null, ex);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -235,9 +239,9 @@ public class ThunderbirdMboxFileIngestService implements IngestServiceAbstractFi
|
|||||||
@Override
|
@Override
|
||||||
public void complete() {
|
public void complete() {
|
||||||
logger.log(Level.INFO, "complete()");
|
logger.log(Level.INFO, "complete()");
|
||||||
managerProxy.postMessage(IngestMessage.createMessage(++messageId, MessageType.INFO, this, "COMPLETE"));
|
services.postMessage(IngestMessage.createMessage(++messageId, MessageType.INFO, this, "COMPLETE"));
|
||||||
|
|
||||||
//service specific cleanup due completion here
|
//module specific cleanup due completion here
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -251,23 +255,23 @@ public class ThunderbirdMboxFileIngestService implements IngestServiceAbstractFi
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void init(IngestManagerProxy managerProxy) {
|
public void init(IngestModuleInit initContext) {
|
||||||
logger.log(Level.INFO, "init()");
|
logger.log(Level.INFO, "init()");
|
||||||
this.managerProxy = managerProxy;
|
services = IngestServices.getDefault();
|
||||||
|
|
||||||
//service specific initialization here
|
//module specific initialization here
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void stop() {
|
public void stop() {
|
||||||
logger.log(Level.INFO, "stop()");
|
logger.log(Level.INFO, "stop()");
|
||||||
|
|
||||||
//service specific cleanup due interruption here
|
//module specific cleanup due interruption here
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ServiceType getType() {
|
public ModuleType getType() {
|
||||||
return ServiceType.AbstractFile;
|
return ModuleType.AbstractFile;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -302,4 +306,21 @@ public class ThunderbirdMboxFileIngestService implements IngestServiceAbstractFi
|
|||||||
@Override
|
@Override
|
||||||
public void saveSimpleConfiguration() {
|
public void saveSimpleConfiguration() {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Process content hierarchy and return true if content is a file and is set as known
|
||||||
|
*/
|
||||||
|
private class GetIsFileKnownVisitor extends ContentVisitor.Default<Boolean> {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected Boolean defaultVisit(Content cntnt) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Boolean visit(org.sleuthkit.datamodel.File file) {
|
||||||
|
return file.getKnown() == TskData.FileKnown.KNOWN;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
@ -2,9 +2,9 @@
|
|||||||
<!DOCTYPE filesystem PUBLIC "-//NetBeans//DTD Filesystem 1.2//EN" "http://www.netbeans.org/dtds/filesystem-1_2.dtd">
|
<!DOCTYPE filesystem PUBLIC "-//NetBeans//DTD Filesystem 1.2//EN" "http://www.netbeans.org/dtds/filesystem-1_2.dtd">
|
||||||
<filesystem>
|
<filesystem>
|
||||||
<folder name="Services">
|
<folder name="Services">
|
||||||
<file name="org-sleuthkit-autopsy-thunderbirdparser-ThunderbirdMboxFilervice.instance">
|
<file name="org-sleuthkit-autopsy-thunderbirdparser-ThunderbirdMboxFileModule.instance">
|
||||||
<attr name="instanceOf" stringvalue="org.sleuthkit.autopsy.ingest.IngestServiceAbstractFile"/>
|
<attr name="instanceOf" stringvalue="org.sleuthkit.autopsy.ingest.IngestModuleAbstractFile"/>
|
||||||
<attr name="instanceCreate" methodvalue="org.sleuthkit.autopsy.thunderbirdparser.ThunderbirdMboxFileIngestService.getDefault"/>
|
<attr name="instanceCreate" methodvalue="org.sleuthkit.autopsy.thunderbirdparser.ThunderbirdMboxFileIngestModule.getDefault"/>
|
||||||
<attr name="position" intvalue="1050"/>
|
<attr name="position" intvalue="1050"/>
|
||||||
</file>
|
</file>
|
||||||
</folder>
|
</folder>
|
||||||
|
Loading…
x
Reference in New Issue
Block a user