Merge branch 'release-4.14.0' of github.com:sleuthkit/autopsy into solr8_libraries

This commit is contained in:
Eugene Livis 2020-01-08 13:46:45 -05:00
commit 52a42b59a8
99 changed files with 918 additions and 432 deletions

View File

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

View File

@ -79,7 +79,7 @@ file.reference.javax.ws.rs-api-2.0.1.jar=release/modules/ext/javax.ws.rs-api-2.0
file.reference.cxf-core-3.0.16.jar=release/modules/ext/cxf-core-3.0.16.jar
file.reference.cxf-rt-frontend-jaxrs-3.0.16.jar=release/modules/ext/cxf-rt-frontend-jaxrs-3.0.16.jar
file.reference.cxf-rt-transports-http-3.0.16.jar=release/modules/ext/cxf-rt-transports-http-3.0.16.jar
file.reference.sleuthkit-postgresql-4.7.0.jar=release/modules/ext/sleuthkit-postgresql-4.7.0.jar
file.reference.sleuthkit-postgresql-4.8.0.jar=release/modules/ext/sleuthkit-postgresql-4.8.0.jar
file.reference.curator-client-2.8.0.jar=release/modules/ext/curator-client-2.8.0.jar
file.reference.curator-framework-2.8.0.jar=release/modules/ext/curator-framework-2.8.0.jar
file.reference.curator-recipes-2.8.0.jar=release/modules/ext/curator-recipes-2.8.0.jar
@ -127,5 +127,5 @@ nbm.homepage=http://www.sleuthkit.org/
nbm.module.author=Brian Carrier
nbm.needs.restart=true
source.reference.curator-recipes-2.8.0.jar=release/modules/ext/curator-recipes-2.8.0-sources.jar
spec.version.base=10.17
spec.version.base=10.18

View File

@ -528,8 +528,8 @@
<binary-origin>release/modules/ext/google-http-client-1.29.0.jar</binary-origin>
</class-path-extension>
<class-path-extension>
<runtime-relative-path>ext/sleuthkit-postgresql-4.7.0.jar</runtime-relative-path>
<binary-origin>release/modules/ext/sleuthkit-postgresql-4.7.0.jar</binary-origin>
<runtime-relative-path>ext/sleuthkit-postgresql-4.8.0.jar</runtime-relative-path>
<binary-origin>release/modules/ext/sleuthkit-postgresql-4.8.0.jar</binary-origin>
</class-path-extension>
<class-path-extension>
<runtime-relative-path>ext/bcpkix-jdk15on-1.60.jar</runtime-relative-path>

View File

@ -354,7 +354,7 @@ UnpackagePortableCaseProgressDialog.title.text=Unpackage Portable Case Progress
UnpackageWorker.doInBackground.canceled=Unpackaging canceled by user
UnpackageWorker.doInBackground.errorCompressingCase=Error unpackaging case
UnpackageWorker.doInBackground.errorFinding7zip=Could not locate 7-Zip executable
UnpackageWorker.doInBackground.previousSeenCase=Case with name {0} has been previously opened do you want to open it again?
UnpackageWorker.doInBackground.previouslySeenCase=Case has been previously opened. Open it again?
UpdateRecentCases.menuItem.clearRecentCases.text=Clear Recent Cases
UpdateRecentCases.menuItem.empty=-Empty-
AddImageWizardIngestConfigPanel.CANCEL_BUTTON.text=Cancel

View File

@ -761,7 +761,7 @@ public class Case {
@Messages({
"Case.progressIndicatorTitle.deletingDataSource=Removing Data Source"
})
public static void deleteDataSourceFromCurrentCase(Long dataSourceObjectID) throws CaseActionException {
static void deleteDataSourceFromCurrentCase(Long dataSourceObjectID) throws CaseActionException {
synchronized (caseActionSerializationLock) {
if (null == currentCase) {
return;

View File

@ -150,14 +150,14 @@ class UnpackagePortableCaseProgressDialog extends javax.swing.JDialog implements
"UnpackageWorker.doInBackground.errorFinding7zip=Could not locate 7-Zip executable",
"UnpackageWorker.doInBackground.errorCompressingCase=Error unpackaging case",
"UnpackageWorker.doInBackground.canceled=Unpackaging canceled by user",
"UnpackageWorker.doInBackground.previousSeenCase=Case with name {0} has been previously opened do you want to open it again?"})
"UnpackageWorker.doInBackground.previouslySeenCase=Case has been previously opened. Open it again?",})
@Override
protected Void doInBackground() throws Exception {
// Check to see if this case has been already opened before
String caseUnpackedBefore = getCaseIfUnpackedBefore(packagedCase);
if ((!caseUnpackedBefore.isEmpty())
&& (MessageNotifyUtil.Message.confirm(Bundle.UnpackageWorker_doInBackground_previousSeenCase(packagedCase)))) {
&& (MessageNotifyUtil.Message.confirm(Bundle.UnpackageWorker_doInBackground_previouslySeenCase()))) {
try {
Case.openAsCurrentCase(caseUnpackedBefore);
success.set(true);

View File

@ -18,16 +18,21 @@
*/
package org.sleuthkit.autopsy.communications.relationships;
import com.google.gson.Gson;
import java.util.Collection;
import java.util.List;
import java.util.Set;
import java.util.logging.Level;
import org.sleuthkit.autopsy.coreutils.ImageUtils;
import org.sleuthkit.autopsy.coreutils.Logger;
import org.sleuthkit.datamodel.AbstractFile;
import org.sleuthkit.datamodel.Account;
import org.sleuthkit.datamodel.BlackboardArtifact;
import org.sleuthkit.datamodel.BlackboardAttribute;
import org.sleuthkit.datamodel.Content;
import org.sleuthkit.datamodel.TskCoreException;
import org.sleuthkit.datamodel.blackboardutils.FileAttachment;
import org.sleuthkit.datamodel.blackboardutils.MessageAttachments;
/**
*
@ -121,10 +126,29 @@ class AccountSummary {
}
}
try {
attachmentCnt += artifact.getChildrenCount();
for (Content childContent : artifact.getChildren()) {
if (ImageUtils.thumbnailSupported(childContent)) {
mediaCnt++;
// count the attachments from the TSK_ATTACHMENTS attribute.
BlackboardAttribute attachmentsAttr = artifact.getAttribute(new BlackboardAttribute.Type(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_ATTACHMENTS));
if (attachmentsAttr != null) {
String jsonVal = attachmentsAttr.getValueString();
MessageAttachments msgAttachments = new Gson().fromJson(jsonVal, MessageAttachments.class);
Collection<FileAttachment> fileAttachments = msgAttachments.getFileAttachments();
for (FileAttachment fileAttachment : fileAttachments) {
attachmentCnt++;
long attachedFileObjId = fileAttachment.getObjectId();
if (attachedFileObjId >= 0) {
AbstractFile attachedFile = artifact.getSleuthkitCase().getAbstractFileById(attachedFileObjId);
if (ImageUtils.thumbnailSupported(attachedFile)) {
mediaCnt++;
}
}
}
} else { // backward compatibility - email message attachments are derived files, children of the message.
attachmentCnt += artifact.getChildrenCount();
for (Content childContent : artifact.getChildren()) {
if (ImageUtils.thumbnailSupported(childContent)) {
mediaCnt++;
}
}
}
} catch (TskCoreException ex) {

View File

@ -36,7 +36,6 @@ import static org.sleuthkit.datamodel.BlackboardAttribute.TSK_BLACKBOARD_ATTRIBU
import org.sleuthkit.datamodel.TimeUtilities;
import org.sleuthkit.datamodel.TskCoreException;
import org.sleuthkit.autopsy.communications.Utils;
import org.sleuthkit.autopsy.coreutils.PhoneNumUtil;
import org.sleuthkit.datamodel.AbstractFile;
import org.sleuthkit.datamodel.Content;

View File

@ -16,12 +16,13 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.sleuthkit.autopsy.coreutils;
package org.sleuthkit.autopsy.communications.relationships;
import com.google.i18n.phonenumbers.NumberParseException;
import com.google.i18n.phonenumbers.PhoneNumberUtil;
import com.google.i18n.phonenumbers.Phonenumber;
import java.util.logging.Level;
import org.sleuthkit.autopsy.coreutils.Logger;
/**
*

View File

@ -29,7 +29,6 @@ import org.openide.util.Lookup;
import org.openide.util.NbBundle.Messages;
import org.sleuthkit.autopsy.centralrepository.datamodel.EamDb;
import org.sleuthkit.datamodel.Account;
import org.sleuthkit.autopsy.coreutils.PhoneNumUtil;
/**
* Account Summary View Panel. This panel shows a list of various counts related

View File

@ -87,13 +87,9 @@ HtmlPanel.showImagesToggleButton.text=Download Images
MediaViewImagePanel.tagsMenu.text_1=Tags Menu
MediaPlayerPanel.progressLabel.text=00:00:00/00:00:00
MediaPlayerPanel.audioSlider.toolTipText=
MediaPlayerPanel.rewindButton.text=\u2bc7\u2bc7
MediaPlayerPanel.fastForwardButton.text=\u2bc8\u2bc8
MediaPlayerPanel.playButton.text=\u25ba
MediaPlayerPanel.rewindButton.text=
MediaPlayerPanel.fastForwardButton.text=
MediaPlayerPanel.playButton.text=
MediaPlayerPanel.infoLabel.text=No Errors
MediaPlayerPanel.VolumeIcon.text=Volume
MediaPlayerPanel.playBackSpeedLabel.text=Speed:
ContextViewer.jSourceGoToResultButton.text=Go to Result
ContextViewer.jSourceNameLabel.text=jSourceNameLabel
ContextViewer.jSourceTextLabel.text=jLabel2
ContextViewer.jSourceLabel.text=Source

View File

@ -10,17 +10,6 @@ AnnotationsContentViewer.title=Annotations
AnnotationsContentViewer.toolTip=Displays tags and comments associated with the selected content.
ApplicationContentViewer.title=Application
ApplicationContentViewer.toolTip=Displays file contents.
ContextViewer.attachmentSource=Attached to:
ContextViewer.downloadedOn=On
ContextViewer.downloadSource=Downloaded from:
ContextViewer.downloadURL=URL
ContextViewer.email=Email
ContextViewer.message=Message
ContextViewer.messageFrom=From
ContextViewer.messageOn=On
ContextViewer.messageTo=From
ContextViewer.title=Context Viewer
ContextViewer.toolTip=Displays context for selected file.
FXVideoPanel.pauseButton.infoLabel.playbackErr=Unable to play video.
FXVideoPanel.progress.bufferingCancelled=media buffering was canceled
FXVideoPanel.progress.bufferingInterrupted=media buffering was interrupted
@ -169,16 +158,12 @@ HtmlPanel.showImagesToggleButton.text=Download Images
MediaViewImagePanel.tagsMenu.text_1=Tags Menu
MediaPlayerPanel.progressLabel.text=00:00:00/00:00:00
MediaPlayerPanel.audioSlider.toolTipText=
MediaPlayerPanel.rewindButton.text=\u2bc7\u2bc7
MediaPlayerPanel.fastForwardButton.text=\u2bc8\u2bc8
MediaPlayerPanel.playButton.text=\u25ba
MediaPlayerPanel.rewindButton.text=
MediaPlayerPanel.fastForwardButton.text=
MediaPlayerPanel.playButton.text=
MediaPlayerPanel.infoLabel.text=No Errors
MediaPlayerPanel.VolumeIcon.text=Volume
MediaPlayerPanel.playBackSpeedLabel.text=Speed:
ContextViewer.jSourceGoToResultButton.text=Go to Result
ContextViewer.jSourceNameLabel.text=jSourceNameLabel
ContextViewer.jSourceTextLabel.text=jLabel2
ContextViewer.jSourceLabel.text=Source
# {0} - tableName
SQLiteViewer.readTable.errorText=Error getting rows for table: {0}
# {0} - tableName

View File

@ -41,7 +41,7 @@
</DimensionLayout>
<DimensionLayout dim="1">
<Group type="103" groupAlignment="0" attributes="0">
<EmptySpace min="0" pref="131" max="32767" attributes="0"/>
<EmptySpace min="0" pref="117" max="32767" attributes="0"/>
</Group>
</DimensionLayout>
</Layout>
@ -83,7 +83,7 @@
<EmptySpace min="-2" pref="5" max="-2" attributes="0"/>
<Group type="103" groupAlignment="0" max="-2" attributes="0">
<Component id="buttonPanel" max="32767" attributes="0"/>
<Component id="playBackPanel" pref="0" max="32767" attributes="0"/>
<Component id="playBackPanel" max="32767" attributes="0"/>
</Group>
<EmptySpace min="-2" pref="14" max="-2" attributes="0"/>
<Component id="infoLabel" min="-2" max="-2" attributes="0"/>
@ -107,7 +107,7 @@
</Property>
</Properties>
<AuxValues>
<AuxValue name="JavaCodeGenerator_InitCodePost" type="java.lang.String" value="progressSlider.setUI(new CircularJSliderUI(progressSlider, new CircularJSliderConfiguration(new Dimension(18,18))));"/>
<AuxValue name="JavaCodeGenerator_InitCodePost" type="java.lang.String" value="progressSlider.setUI(new CircularJSliderUI(progressSlider, new Dimension(18,18)));"/>
</AuxValues>
</Component>
<Component class="javax.swing.JLabel" name="progressLabel">
@ -123,9 +123,21 @@
<SubComponents>
<Component class="javax.swing.JButton" name="playButton">
<Properties>
<Property name="icon" type="javax.swing.Icon" editor="org.netbeans.modules.form.editors2.IconEditor">
<Image iconType="3" name="/org/sleuthkit/autopsy/contentviewers/images/Play-arrow-01.png"/>
</Property>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/contentviewers/Bundle.properties" key="MediaPlayerPanel.playButton.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
<Property name="maximumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[53, 29]"/>
</Property>
<Property name="minimumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[53, 29]"/>
</Property>
<Property name="preferredSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[49, 29]"/>
</Property>
</Properties>
<Events>
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="playButtonActionPerformed"/>
@ -138,6 +150,9 @@
</Component>
<Component class="javax.swing.JButton" name="fastForwardButton">
<Properties>
<Property name="icon" type="javax.swing.Icon" editor="org.netbeans.modules.form.editors2.IconEditor">
<Image iconType="3" name="/org/sleuthkit/autopsy/contentviewers/images/Fast-forward-01.png"/>
</Property>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/contentviewers/Bundle.properties" key="MediaPlayerPanel.fastForwardButton.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
@ -153,6 +168,9 @@
</Component>
<Component class="javax.swing.JButton" name="rewindButton">
<Properties>
<Property name="icon" type="javax.swing.Icon" editor="org.netbeans.modules.form.editors2.IconEditor">
<Image iconType="3" name="/org/sleuthkit/autopsy/contentviewers/images/Fast-rewind-01.png"/>
</Property>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/contentviewers/Bundle.properties" key="MediaPlayerPanel.rewindButton.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
@ -172,6 +190,15 @@
<ResourceString bundle="org/sleuthkit/autopsy/contentviewers/Bundle.properties" key="MediaPlayerPanel.VolumeIcon.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
<Property name="horizontalTextPosition" type="int" value="2"/>
<Property name="maximumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[34, 29]"/>
</Property>
<Property name="minimumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[34, 29]"/>
</Property>
<Property name="preferredSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[34, 19]"/>
</Property>
</Properties>
<Constraints>
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
@ -188,15 +215,19 @@
<ResourceString bundle="org/sleuthkit/autopsy/contentviewers/Bundle.properties" key="MediaPlayerPanel.audioSlider.toolTipText" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
<Property name="value" type="int" value="25"/>
<Property name="maximumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[32767, 19]"/>
</Property>
<Property name="minimumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[200, 21]"/>
<Dimension value="[200, 19]"/>
</Property>
<Property name="preferredSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[200, 21]"/>
<Dimension value="[200, 30]"/>
</Property>
<Property name="requestFocusEnabled" type="boolean" value="false"/>
</Properties>
<AuxValues>
<AuxValue name="JavaCodeGenerator_InitCodePost" type="java.lang.String" value="audioSlider.setUI(new CircularJSliderUI(audioSlider, new CircularJSliderConfiguration(new Dimension(15,15))));"/>
<AuxValue name="JavaCodeGenerator_InitCodePost" type="java.lang.String" value="audioSlider.setUI(new CircularJSliderUI(audioSlider, new Dimension(15,15)));"/>
</AuxValues>
<Constraints>
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
@ -223,7 +254,7 @@
<DimensionLayout dim="0">
<Group type="103" groupAlignment="0" attributes="0">
<Group type="102" alignment="0" attributes="0">
<Component id="playBackSpeedLabel" min="-2" max="-2" attributes="0"/>
<Component id="playBackSpeedLabel" min="-2" pref="34" max="-2" attributes="0"/>
<EmptySpace max="32767" attributes="0"/>
<Component id="playBackSpeedComboBox" min="-2" max="-2" attributes="0"/>
<EmptySpace min="-2" pref="13" max="-2" attributes="0"/>
@ -233,12 +264,15 @@
<DimensionLayout dim="1">
<Group type="103" groupAlignment="0" attributes="0">
<Group type="102" alignment="0" attributes="0">
<EmptySpace min="-2" pref="6" max="-2" attributes="0"/>
<Group type="103" groupAlignment="3" attributes="0">
<Component id="playBackSpeedComboBox" alignment="3" min="-2" max="-2" attributes="0"/>
<Component id="playBackSpeedLabel" alignment="3" min="-2" max="-2" attributes="0"/>
<EmptySpace min="-2" pref="7" max="-2" attributes="0"/>
<Group type="103" groupAlignment="0" max="-2" attributes="0">
<Group type="102" attributes="0">
<EmptySpace min="2" pref="2" max="-2" attributes="0"/>
<Component id="playBackSpeedLabel" max="32767" attributes="0"/>
</Group>
<Component id="playBackSpeedComboBox" min="-2" max="-2" attributes="0"/>
</Group>
<EmptySpace max="32767" attributes="0"/>
<EmptySpace min="-2" pref="10" max="-2" attributes="0"/>
</Group>
</Group>
</DimensionLayout>
@ -260,14 +294,15 @@
</Property>
<Property name="selectedIndex" type="int" value="3"/>
<Property name="maximumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[53, 23]"/>
<Dimension value="[53, 29]"/>
</Property>
<Property name="minimumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[53, 23]"/>
<Dimension value="[53, 29]"/>
</Property>
<Property name="preferredSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[53, 23]"/>
<Dimension value="[53, 29]"/>
</Property>
<Property name="requestFocusEnabled" type="boolean" value="false"/>
</Properties>
<Events>
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="playBackSpeedComboBoxActionPerformed"/>
@ -281,6 +316,15 @@
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/contentviewers/Bundle.properties" key="MediaPlayerPanel.playBackSpeedLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
<Property name="maximumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[34, 19]"/>
</Property>
<Property name="minimumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[34, 19]"/>
</Property>
<Property name="preferredSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[34, 19]"/>
</Property>
</Properties>
</Component>
</SubComponents>

View File

@ -1,7 +1,7 @@
/*
* Autopsy Forensic Browser
*
* Copyright 2013-2019 Basis Technology Corp.
* Copyright 2013-2020 Basis Technology Corp.
* Contact: carrier <at> sleuthkit <dot> org
*
* Licensed under the Apache License, Version 2.0 (the "License");
@ -29,6 +29,7 @@ import java.awt.RenderingHints;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.io.File;
import java.io.IOException;
import java.util.Arrays;
@ -61,6 +62,7 @@ import org.sleuthkit.autopsy.modules.filetypeid.FileTypeDetector;
import org.sleuthkit.datamodel.AbstractFile;
import org.sleuthkit.datamodel.TskData;
import javafx.embed.swing.JFXPanel;
import javax.swing.ImageIcon;
import javax.swing.JComponent;
import javax.swing.JSlider;
import javax.swing.SwingUtilities;
@ -72,6 +74,7 @@ import org.freedesktop.gstreamer.Format;
import org.freedesktop.gstreamer.GstException;
import org.freedesktop.gstreamer.event.SeekFlags;
import org.freedesktop.gstreamer.event.SeekType;
import org.sleuthkit.autopsy.coreutils.PlatformUtil;
/**
* This is a video player that is part of the Media View layered pane. It uses
@ -109,7 +112,7 @@ public class MediaPlayerPanel extends JPanel implements MediaFileViewer.MediaVie
".wav",
".webm",
".wma",
".wmv",}; //NON-NLS
".wmv"}; //NON-NLS
private static final List<String> MIME_TYPES = Arrays.asList(
"video/3gpp",
"video/3gpp2",
@ -200,15 +203,18 @@ public class MediaPlayerPanel extends JPanel implements MediaFileViewer.MediaVie
private static final int PROGRESS_SLIDER_SIZE = 2000;
private static final int SKIP_IN_SECONDS = 30;
private final ImageIcon playIcon = new ImageIcon(getClass().getResource("/org/sleuthkit/autopsy/contentviewers/images/Play-arrow-01.png"));
private final ImageIcon pauseIcon = new ImageIcon(getClass().getResource("/org/sleuthkit/autopsy/contentviewers/images/Pause-01.png"));
private ExtractMedia extractMediaWorker;
//Serialize setting the value of the Video progress slider.
//The slider is a shared resource between the VideoPanelUpdater
//and the TrackListener of the JSliderUI.
//and the TrackListener on the slider itself.
private final Semaphore sliderLock;
/**
* Creates new form MediaViewVideoPanel
* Creates a new MediaPlayerPanel
*/
public MediaPlayerPanel() throws GstException, UnsatisfiedLinkError {
initComponents();
@ -216,6 +222,14 @@ public class MediaPlayerPanel extends JPanel implements MediaFileViewer.MediaVie
//True for fairness. In other words,
//acquire() calls are processed in order of invocation.
sliderLock = new Semaphore(1, true);
/**
* See JIRA-5888 for details. Initializing gstreamer here is more stable
* on Windows.
*/
if (PlatformUtil.isWindowsOS()) {
Gst.init();
}
}
private void customizeComponents() {
@ -247,7 +261,37 @@ public class MediaPlayerPanel extends JPanel implements MediaFileViewer.MediaVie
}
}
});
//Manage the audio level when the user is adjusting the volumn slider
//Manage the video while the user is performing actions on the track.
progressSlider.addMouseListener(new MouseListener() {
private State previousState = State.NULL;
@Override
public void mousePressed(MouseEvent e) {
previousState = gstPlayBin.getState();
gstPlayBin.pause();
}
@Override
public void mouseReleased(MouseEvent e) {
if(previousState.equals(State.PLAYING)) {
gstPlayBin.play();
}
previousState = State.NULL;
}
@Override
public void mouseClicked(MouseEvent e) {
}
@Override
public void mouseEntered(MouseEvent e) {
}
@Override
public void mouseExited(MouseEvent e) {
}
});
//Manage the audio level when the user is adjusting the volume slider
audioSlider.addChangeListener((ChangeEvent event) -> {
if (audioSlider.getValueIsAdjusting()) {
double audioPercent = (audioSlider.getValue() * 2.0) / 100.0;
@ -271,11 +315,11 @@ public class MediaPlayerPanel extends JPanel implements MediaFileViewer.MediaVie
public void stateChanged(GstObject go, State oldState, State currentState, State pendingState) {
if (State.PLAYING.equals(currentState)) {
SwingUtilities.invokeLater(() -> {
playButton.setText("||");
playButton.setIcon(pauseIcon);
});
} else {
SwingUtilities.invokeLater(() -> {
playButton.setText("");
playButton.setIcon(playIcon);
});
}
}
@ -504,8 +548,10 @@ public class MediaPlayerPanel extends JPanel implements MediaFileViewer.MediaVie
// Initialize Gstreamer. It is safe to call this for every file.
// It was moved here from the constructor because having it happen
// earlier resulted in conflicts on Linux.
Gst.init();
// earlier resulted in conflicts on Linux. See JIRA-5888.
if (!PlatformUtil.isWindowsOS()) {
Gst.init();
}
//Video is ready for playback. Create new components
gstPlayBin = new PlayBin("VideoPlayer", tempFile.toURI());
@ -574,63 +620,15 @@ public class MediaPlayerPanel extends JPanel implements MediaFileViewer.MediaVie
}
}
/**
* Represents the default configuration for the circular JSliderUI.
*/
private class CircularJSliderConfiguration {
//Thumb configurations
private final Color thumbColor;
private final Dimension thumbDimension;
//Track configurations
//Progress bar can be bisected into a seen group
//and an unseen group.
private final Color unseen;
private final Color seen;
/**
* Default configuration
*
* JSlider is light blue RGB(0,130,255). Seen track is light blue
* RGB(0,130,255). Unseen track is light grey RGB(192, 192, 192).
*
* @param thumbDimension Size of the oval thumb.
*/
public CircularJSliderConfiguration(Dimension thumbDimension) {
Color lightBlue = new Color(0, 130, 255);
seen = lightBlue;
unseen = Color.LIGHT_GRAY;
thumbColor = lightBlue;
this.thumbDimension = new Dimension(thumbDimension);
}
public Color getThumbColor() {
return thumbColor;
}
public Color getUnseenTrackColor() {
return unseen;
}
public Color getSeenTrackColor() {
return seen;
}
public Dimension getThumbDimension() {
return new Dimension(thumbDimension);
}
}
/**
* Custom view for the JSlider.
*/
private class CircularJSliderUI extends BasicSliderUI {
private final CircularJSliderConfiguration config;
private final Dimension thumbDimension;
private final Color thumbColor;
private final Color trackUnseen;
private final Color trackSeen;
/**
* Creates a custom view for the JSlider. This view draws a blue oval
@ -641,18 +639,25 @@ public class MediaPlayerPanel extends JPanel implements MediaFileViewer.MediaVie
* @param config Configuration object. Contains info about thumb
* dimensions and colors.
*/
public CircularJSliderUI(JSlider slider, CircularJSliderConfiguration config) {
public CircularJSliderUI(JSlider slider, Dimension thumbDimension) {
super(slider);
this.config = config;
this.thumbDimension = thumbDimension;
//Configure track and thumb colors.
Color lightBlue = new Color(0, 130, 255);
thumbColor = lightBlue;
trackSeen = lightBlue;
trackUnseen = Color.LIGHT_GRAY;
}
@Override
protected Dimension getThumbSize() {
return config.getThumbDimension();
return new Dimension(thumbDimension);
}
/**
* Modifies the View to be an oval rather than the rectangle Controller.
* Modifies the View to be an oval rather than the underlying
* rectangle Controller.
*/
@Override
public void paintThumb(Graphics graphic) {
@ -662,8 +667,7 @@ public class MediaPlayerPanel extends JPanel implements MediaFileViewer.MediaVie
//Change the thumb view from the rectangle
//controller to an oval.
graphic.setColor(config.getThumbColor());
Dimension thumbDimension = config.getThumbDimension();
graphic.setColor(thumbColor);
graphic.fillOval(thumb.x, thumb.y, thumbDimension.width, thumbDimension.height);
//Preserve the graphics original color
@ -686,12 +690,12 @@ public class MediaPlayerPanel extends JPanel implements MediaFileViewer.MediaVie
Color original = graphic.getColor();
//Paint the seen side
graphic.setColor(config.getSeenTrackColor());
graphic.setColor(trackSeen);
graphic.drawLine(track.x, track.y + track.height / 2,
thumbX, thumbY + track.height / 2);
//Paint the unseen side
graphic.setColor(config.getUnseenTrackColor());
graphic.setColor(trackUnseen);
graphic.drawLine(thumbX, thumbY + track.height / 2,
track.x + track.width, track.y + track.height / 2);
@ -701,7 +705,26 @@ public class MediaPlayerPanel extends JPanel implements MediaFileViewer.MediaVie
@Override
protected TrackListener createTrackListener(JSlider slider) {
return new CustomTrackListener();
/**
* This track listener will force the thumb to be snapped to the mouse
* location. This makes grabbing and dragging the JSlider much easier.
* Using the default track listener, the user would have to click
* exactly on the slider thumb to drag it. Now the thumb positions
* itself under the mouse so that it can always be dragged.
*/
return new TrackListener() {
@Override
public void mousePressed(MouseEvent e) {
if (!slider.isEnabled() || !SwingUtilities.isLeftMouseButton(e)) {
return;
}
//Snap the thumb to position of the mouse
scrollDueToClickInTrack(0);
//Handle the event as normal.
super.mousePressed(e);
}
};
}
@Override
@ -715,7 +738,7 @@ public class MediaPlayerPanel extends JPanel implements MediaFileViewer.MediaVie
int value = this.valueForXPosition(mousePosition.x);
//Lock the slider down, which is a shared resource.
//The VideoPanelUpdater (dedicated thread) keeps the
//The VideoPanelUpdater keeps the
//slider in sync with the video position, so without
//proper locking our change could be overwritten.
sliderLock.acquireUninterruptibly();
@ -738,43 +761,6 @@ public class MediaPlayerPanel extends JPanel implements MediaFileViewer.MediaVie
super.update(graphic, component);
}
/**
* This track listener will force the thumb to be snapped to the mouse
* location. This makes grabbing and dragging the JSlider much easier.
* Using the default track listener, the user would have to click
* exactly on the slider thumb to drag it. Now the thumb positions
* itself under the mouse so that it can always be dragged.
*/
private class CustomTrackListener extends CircularJSliderUI.TrackListener {
@Override
public void mousePressed(MouseEvent e) {
if (!slider.isEnabled()) {
return;
}
//Snap the thumb to position of the mouse
scrollDueToClickInTrack(0);
//Pause the video for convenience
gstPlayBin.pause();
//Handle the event as normal.
super.mousePressed(e);
}
@Override
public void mouseReleased(MouseEvent e) {
if (!slider.isEnabled()) {
return;
}
super.mouseReleased(e);
//Unpause once the mouse has been released.
gstPlayBin.play();
}
}
}
/**
@ -810,7 +796,7 @@ public class MediaPlayerPanel extends JPanel implements MediaFileViewer.MediaVie
);
videoPanelLayout.setVerticalGroup(
videoPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGap(0, 131, Short.MAX_VALUE)
.addGap(0, 117, Short.MAX_VALUE)
);
progressSlider.setValue(0);
@ -818,13 +804,17 @@ public class MediaPlayerPanel extends JPanel implements MediaFileViewer.MediaVie
progressSlider.setDoubleBuffered(true);
progressSlider.setMinimumSize(new java.awt.Dimension(36, 21));
progressSlider.setPreferredSize(new java.awt.Dimension(200, 21));
progressSlider.setUI(new CircularJSliderUI(progressSlider, new CircularJSliderConfiguration(new Dimension(18,18))));
progressSlider.setUI(new CircularJSliderUI(progressSlider, new Dimension(18,18)));
org.openide.awt.Mnemonics.setLocalizedText(progressLabel, org.openide.util.NbBundle.getMessage(MediaPlayerPanel.class, "MediaPlayerPanel.progressLabel.text")); // NOI18N
buttonPanel.setLayout(new java.awt.GridBagLayout());
playButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/org/sleuthkit/autopsy/contentviewers/images/Play-arrow-01.png"))); // NOI18N
org.openide.awt.Mnemonics.setLocalizedText(playButton, org.openide.util.NbBundle.getMessage(MediaPlayerPanel.class, "MediaPlayerPanel.playButton.text")); // NOI18N
playButton.setMaximumSize(new java.awt.Dimension(53, 29));
playButton.setMinimumSize(new java.awt.Dimension(53, 29));
playButton.setPreferredSize(new java.awt.Dimension(49, 29));
playButton.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
playButtonActionPerformed(evt);
@ -838,6 +828,7 @@ public class MediaPlayerPanel extends JPanel implements MediaFileViewer.MediaVie
gridBagConstraints.insets = new java.awt.Insets(5, 6, 0, 0);
buttonPanel.add(playButton, gridBagConstraints);
fastForwardButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/org/sleuthkit/autopsy/contentviewers/images/Fast-forward-01.png"))); // NOI18N
org.openide.awt.Mnemonics.setLocalizedText(fastForwardButton, org.openide.util.NbBundle.getMessage(MediaPlayerPanel.class, "MediaPlayerPanel.fastForwardButton.text")); // NOI18N
fastForwardButton.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
@ -851,6 +842,7 @@ public class MediaPlayerPanel extends JPanel implements MediaFileViewer.MediaVie
gridBagConstraints.insets = new java.awt.Insets(5, 6, 0, 0);
buttonPanel.add(fastForwardButton, gridBagConstraints);
rewindButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/org/sleuthkit/autopsy/contentviewers/images/Fast-rewind-01.png"))); // NOI18N
org.openide.awt.Mnemonics.setLocalizedText(rewindButton, org.openide.util.NbBundle.getMessage(MediaPlayerPanel.class, "MediaPlayerPanel.rewindButton.text")); // NOI18N
rewindButton.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
@ -866,6 +858,9 @@ public class MediaPlayerPanel extends JPanel implements MediaFileViewer.MediaVie
org.openide.awt.Mnemonics.setLocalizedText(VolumeIcon, org.openide.util.NbBundle.getMessage(MediaPlayerPanel.class, "MediaPlayerPanel.VolumeIcon.text")); // NOI18N
VolumeIcon.setHorizontalTextPosition(javax.swing.SwingConstants.LEFT);
VolumeIcon.setMaximumSize(new java.awt.Dimension(34, 29));
VolumeIcon.setMinimumSize(new java.awt.Dimension(34, 29));
VolumeIcon.setPreferredSize(new java.awt.Dimension(34, 19));
gridBagConstraints = new java.awt.GridBagConstraints();
gridBagConstraints.gridx = 3;
gridBagConstraints.gridy = 0;
@ -880,9 +875,11 @@ public class MediaPlayerPanel extends JPanel implements MediaFileViewer.MediaVie
audioSlider.setMinorTickSpacing(5);
audioSlider.setToolTipText(org.openide.util.NbBundle.getMessage(MediaPlayerPanel.class, "MediaPlayerPanel.audioSlider.toolTipText")); // NOI18N
audioSlider.setValue(25);
audioSlider.setMinimumSize(new java.awt.Dimension(200, 21));
audioSlider.setPreferredSize(new java.awt.Dimension(200, 21));
audioSlider.setUI(new CircularJSliderUI(audioSlider, new CircularJSliderConfiguration(new Dimension(15,15))));
audioSlider.setMaximumSize(new java.awt.Dimension(32767, 19));
audioSlider.setMinimumSize(new java.awt.Dimension(200, 19));
audioSlider.setPreferredSize(new java.awt.Dimension(200, 30));
audioSlider.setRequestFocusEnabled(false);
audioSlider.setUI(new CircularJSliderUI(audioSlider, new Dimension(15,15)));
gridBagConstraints = new java.awt.GridBagConstraints();
gridBagConstraints.gridx = 4;
gridBagConstraints.gridy = 0;
@ -898,9 +895,10 @@ public class MediaPlayerPanel extends JPanel implements MediaFileViewer.MediaVie
playBackSpeedComboBox.setModel(new javax.swing.DefaultComboBoxModel<>(new String[] { "0.25x", "0.50x", "0.75x", "1x", "1.25x", "1.50x", "1.75x", "2x" }));
playBackSpeedComboBox.setSelectedIndex(3);
playBackSpeedComboBox.setMaximumSize(new java.awt.Dimension(53, 23));
playBackSpeedComboBox.setMinimumSize(new java.awt.Dimension(53, 23));
playBackSpeedComboBox.setPreferredSize(new java.awt.Dimension(53, 23));
playBackSpeedComboBox.setMaximumSize(new java.awt.Dimension(53, 29));
playBackSpeedComboBox.setMinimumSize(new java.awt.Dimension(53, 29));
playBackSpeedComboBox.setPreferredSize(new java.awt.Dimension(53, 29));
playBackSpeedComboBox.setRequestFocusEnabled(false);
playBackSpeedComboBox.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
playBackSpeedComboBoxActionPerformed(evt);
@ -908,13 +906,16 @@ public class MediaPlayerPanel extends JPanel implements MediaFileViewer.MediaVie
});
org.openide.awt.Mnemonics.setLocalizedText(playBackSpeedLabel, org.openide.util.NbBundle.getMessage(MediaPlayerPanel.class, "MediaPlayerPanel.playBackSpeedLabel.text")); // NOI18N
playBackSpeedLabel.setMaximumSize(new java.awt.Dimension(34, 19));
playBackSpeedLabel.setMinimumSize(new java.awt.Dimension(34, 19));
playBackSpeedLabel.setPreferredSize(new java.awt.Dimension(34, 19));
javax.swing.GroupLayout playBackPanelLayout = new javax.swing.GroupLayout(playBackPanel);
playBackPanel.setLayout(playBackPanelLayout);
playBackPanelLayout.setHorizontalGroup(
playBackPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(playBackPanelLayout.createSequentialGroup()
.addComponent(playBackSpeedLabel)
.addComponent(playBackSpeedLabel, javax.swing.GroupLayout.PREFERRED_SIZE, 34, javax.swing.GroupLayout.PREFERRED_SIZE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addComponent(playBackSpeedComboBox, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addGap(13, 13, 13))
@ -922,11 +923,13 @@ public class MediaPlayerPanel extends JPanel implements MediaFileViewer.MediaVie
playBackPanelLayout.setVerticalGroup(
playBackPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(playBackPanelLayout.createSequentialGroup()
.addGap(6, 6, 6)
.addGroup(playBackPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
.addComponent(playBackSpeedComboBox, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addComponent(playBackSpeedLabel))
.addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
.addGap(7, 7, 7)
.addGroup(playBackPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false)
.addGroup(playBackPanelLayout.createSequentialGroup()
.addGap(2, 2, 2)
.addComponent(playBackSpeedLabel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
.addComponent(playBackSpeedComboBox, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
.addGap(10, 10, 10))
);
javax.swing.GroupLayout controlPanelLayout = new javax.swing.GroupLayout(controlPanel);
@ -958,7 +961,7 @@ public class MediaPlayerPanel extends JPanel implements MediaFileViewer.MediaVie
.addGap(5, 5, 5)
.addGroup(controlPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false)
.addComponent(buttonPanel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addComponent(playBackPanel, javax.swing.GroupLayout.PREFERRED_SIZE, 0, Short.MAX_VALUE))
.addComponent(playBackPanel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
.addGap(14, 14, 14)
.addComponent(infoLabel))
);
@ -1002,13 +1005,21 @@ public class MediaPlayerPanel extends JPanel implements MediaFileViewer.MediaVie
long currentTime = gstPlayBin.queryPosition(TimeUnit.NANOSECONDS);
//Skip 30 seconds.
long fastForwardDelta = TimeUnit.NANOSECONDS.convert(SKIP_IN_SECONDS, TimeUnit.SECONDS);
//Ignore fast forward requests if there are less than 30 seconds left.
if (currentTime + fastForwardDelta >= duration) {
//Don't allow skipping within 2 seconds of video ending. Skipping right to
//the end causes undefined behavior for some gstreamer plugins.
long twoSecondsInNano = TimeUnit.NANOSECONDS.convert(2, TimeUnit.SECONDS);
if((duration - currentTime) <= twoSecondsInNano) {
return;
}
long newTime;
if (currentTime + fastForwardDelta >= duration) {
//If there are less than 30 seconds left, only fast forward to the midpoint.
newTime = currentTime + (duration - currentTime)/2;
} else {
newTime = currentTime + fastForwardDelta;
}
long newTime = currentTime + fastForwardDelta;
double playBackRate = getPlayBackRate();
gstPlayBin.seek(playBackRate,
Format.TIME,

View File

@ -39,6 +39,8 @@ import org.openide.nodes.Children;
import org.openide.nodes.Node;
import org.openide.util.NbBundle;
import org.openide.util.lookup.ServiceProvider;
import org.sleuthkit.autopsy.casemodule.Case;
import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException;
import org.sleuthkit.autopsy.corecomponentinterfaces.DataContentViewer;
import org.sleuthkit.autopsy.corecomponents.DataResultPanel;
import org.sleuthkit.autopsy.corecomponents.TableFilterNode;
@ -47,6 +49,7 @@ import org.sleuthkit.autopsy.directorytree.DataResultFilterNode;
import org.sleuthkit.autopsy.directorytree.NewWindowViewAction;
import org.sleuthkit.datamodel.AbstractFile;
import org.sleuthkit.datamodel.BlackboardArtifact;
import static org.sleuthkit.datamodel.BlackboardArtifact.ARTIFACT_TYPE.TSK_ASSOCIATED_OBJECT;
import static org.sleuthkit.datamodel.BlackboardArtifact.ARTIFACT_TYPE.TSK_EMAIL_MSG;
import static org.sleuthkit.datamodel.BlackboardArtifact.ARTIFACT_TYPE.TSK_KEYWORD_HIT;
import static org.sleuthkit.datamodel.BlackboardArtifact.ARTIFACT_TYPE.TSK_MESSAGE;
@ -67,6 +70,7 @@ import static org.sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE.TSK_PHO
import static org.sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE.TSK_SUBJECT;
import static org.sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE.TSK_TEXT;
import org.sleuthkit.datamodel.Content;
import org.sleuthkit.datamodel.SleuthkitCase;
import org.sleuthkit.datamodel.TskCoreException;
import org.sleuthkit.datamodel.blackboardutils.FileAttachment;
import org.sleuthkit.datamodel.blackboardutils.MessageAttachments;
@ -370,7 +374,7 @@ public class MessageContentViewer extends javax.swing.JPanel implements DataCont
return;
}
artifact = node.getLookup().lookup(BlackboardArtifact.class);
artifact = getNodeArtifact(node);
if (artifact == null) {
resetComponent();
return;
@ -465,7 +469,7 @@ public class MessageContentViewer extends javax.swing.JPanel implements DataCont
@Override
public boolean isSupported(Node node) {
BlackboardArtifact nodeArtifact = node.getLookup().lookup(BlackboardArtifact.class);
BlackboardArtifact nodeArtifact = getNodeArtifact(node);
if (nodeArtifact == null) {
return false;
@ -498,10 +502,56 @@ public class MessageContentViewer extends javax.swing.JPanel implements DataCont
|| artifactTypeID == TSK_MESSAGE.getTypeID();
}
/**
* Returns the artifact represented by node.
*
* If the node lookup has an artifact, that artifact is returned. However,
* if the node lookup is a file, then we look for a TSK_ASSOCIATED_OBJECT
* artifact on the file, and if a message artifact is found associated with
* the file, that artifact is returned.
*
* @param node Node to check.
* @return Blackboard artifact for the node, null if there isn't any.
*/
private BlackboardArtifact getNodeArtifact(Node node) {
BlackboardArtifact nodeArtifact = node.getLookup().lookup(BlackboardArtifact.class);
if (nodeArtifact == null) {
try {
SleuthkitCase tskCase = Case.getCurrentCaseThrows().getSleuthkitCase();
AbstractFile file = node.getLookup().lookup(AbstractFile.class);
if (file != null) {
List<BlackboardArtifact> artifactsList = tskCase.getBlackboardArtifacts(TSK_ASSOCIATED_OBJECT, file.getId());
for (BlackboardArtifact fileArtifact : artifactsList) {
BlackboardAttribute associatedArtifactAttribute = fileArtifact.getAttribute(new BlackboardAttribute.Type(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_ASSOCIATED_ARTIFACT));
if (associatedArtifactAttribute != null) {
BlackboardArtifact associatedArtifact = fileArtifact.getSleuthkitCase().getBlackboardArtifact(associatedArtifactAttribute.getValueLong());
if (isMessageArtifact(associatedArtifact)) {
nodeArtifact = associatedArtifact;
}
}
}
}
} catch (NoCurrentCaseException | TskCoreException ex) {
LOGGER.log(Level.SEVERE, "Failed to get file for selected node.", ex); //NON-NLS
}
}
return nodeArtifact;
}
@Override
public int isPreferred(Node node) {
// For message artifacts this is a high priority viewer,
// but for attachment files, this a lower priority vewer.
if (isSupported(node)) {
return 7;
BlackboardArtifact nodeArtifact = node.getLookup().lookup(BlackboardArtifact.class);
if (nodeArtifact != null) {
return 7;
} else {
return 1;
}
}
return 0;
}

View File

@ -0,0 +1,4 @@
ContextViewer.jSourceGoToResultButton.text=Go to Result
ContextViewer.jSourceTextLabel.text=jLabel2
ContextViewer.jSourceNameLabel.text=jSourceNameLabel
ContextViewer.jSourceLabel.text=Source

View File

@ -0,0 +1,15 @@
ContextViewer.attachmentSource=Attached to:
ContextViewer.downloadedOn=On
ContextViewer.downloadSource=Downloaded from:
ContextViewer.downloadURL=URL
ContextViewer.email=Email
ContextViewer.jSourceGoToResultButton.text=Go to Result
ContextViewer.jSourceTextLabel.text=jLabel2
ContextViewer.jSourceNameLabel.text=jSourceNameLabel
ContextViewer.jSourceLabel.text=Source
ContextViewer.message=Message
ContextViewer.messageFrom=From
ContextViewer.messageOn=On
ContextViewer.messageTo=To
ContextViewer.title=Context
ContextViewer.toolTip=Displays context for selected file.

View File

@ -65,16 +65,12 @@
<Component class="javax.swing.JButton" name="jSourceGoToResultButton">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/contentviewers/Bundle.properties" key="ContextViewer.jSourceGoToResultButton.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
<ResourceString bundle="org/sleuthkit/autopsy/contentviewers/contextviewer/Bundle.properties" key="ContextViewer.jSourceGoToResultButton.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
</Properties>
<Events>
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="jSourceGoToResultButtonActionPerformed"/>
</Events>
<AuxValues>
<AuxValue name="JavaCodeGenerator_VariableLocal" type="java.lang.Boolean" value="true"/>
<AuxValue name="JavaCodeGenerator_VariableModifier" type="java.lang.Integer" value="0"/>
</AuxValues>
</Component>
<Component class="javax.swing.JLabel" name="jSourceLabel">
<Properties>
@ -82,25 +78,21 @@
<Font name="Dialog" size="14" style="1"/>
</Property>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/contentviewers/Bundle.properties" key="ContextViewer.jSourceLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
<ResourceString bundle="org/sleuthkit/autopsy/contentviewers/contextviewer/Bundle.properties" key="ContextViewer.jSourceLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
</Properties>
<AuxValues>
<AuxValue name="JavaCodeGenerator_VariableLocal" type="java.lang.Boolean" value="true"/>
<AuxValue name="JavaCodeGenerator_VariableModifier" type="java.lang.Integer" value="0"/>
</AuxValues>
</Component>
<Component class="javax.swing.JLabel" name="jSourceNameLabel">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/contentviewers/Bundle.properties" key="ContextViewer.jSourceNameLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
<ResourceString bundle="org/sleuthkit/autopsy/contentviewers/contextviewer/Bundle.properties" key="ContextViewer.jSourceNameLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
</Properties>
</Component>
<Component class="javax.swing.JLabel" name="jSourceTextLabel">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/contentviewers/Bundle.properties" key="ContextViewer.jSourceTextLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
<ResourceString bundle="org/sleuthkit/autopsy/contentviewers/contextviewer/Bundle.properties" key="ContextViewer.jSourceTextLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
</Properties>
</Component>

View File

@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.sleuthkit.autopsy.contentviewers;
package org.sleuthkit.autopsy.contentviewers.contextviewer;
import java.awt.Component;
import java.util.ArrayList;
@ -79,8 +79,8 @@ public final class ContextViewer extends javax.swing.JPanel implements DataConte
// <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
private void initComponents() {
javax.swing.JButton jSourceGoToResultButton = new javax.swing.JButton();
javax.swing.JLabel jSourceLabel = new javax.swing.JLabel();
jSourceGoToResultButton = new javax.swing.JButton();
jSourceLabel = new javax.swing.JLabel();
jSourceNameLabel = new javax.swing.JLabel();
jSourceTextLabel = new javax.swing.JLabel();
@ -165,7 +165,7 @@ public final class ContextViewer extends javax.swing.JPanel implements DataConte
"ContextViewer.title=Context",
"ContextViewer.toolTip=Displays context for selected file."
})
@Override
public String getTitle() {
return Bundle.ContextViewer_title();
@ -188,6 +188,7 @@ public final class ContextViewer extends javax.swing.JPanel implements DataConte
@Override
public void resetComponent() {
jSourceGoToResultButton.setVisible(false);
setSourceName("");
setSourceText("");
}
@ -238,23 +239,23 @@ public final class ContextViewer extends javax.swing.JPanel implements DataConte
boolean foundASource = false;
for (BlackboardArtifact.ARTIFACT_TYPE artifactType : SOURCE_CONTEXT_ARTIFACTS) {
List<BlackboardArtifact> artifactsList = tskCase.getBlackboardArtifacts(artifactType, sourceFile.getId());
foundASource = !artifactsList.isEmpty();
for (BlackboardArtifact contextArtifact : artifactsList) {
addSourceEntry(contextArtifact);
}
}
jSourceGoToResultButton.setVisible(true);
if (foundASource == false) {
setSourceName("Unknown");
showSourceText(false);
}
}
/**
* Adds a source context entry for the selected file based on the given context
* providing artifact.
* Adds a source context entry for the selected file based on the given
* context providing artifact.
*
* @param artifact Artifact that may provide context.
*
@ -315,15 +316,17 @@ public final class ContextViewer extends javax.swing.JPanel implements DataConte
/**
* Sets the source text string.
*
* @param nameLabel String value for source text.
* @param text String value for source text.
*/
private void setSourceText(String text) {
jSourceTextLabel.setText(text);
showSourceText(true);
showSourceText(!text.isEmpty());
}
private void showSourceText(boolean isVisible) {
jSourceTextLabel.setVisible(isVisible);
private void showSourceText(boolean show) {
jSourceTextLabel.setVisible(show);
jSourceGoToResultButton.setEnabled(show);
jSourceLabel.setVisible(show);
}
/**
@ -366,8 +369,7 @@ public final class ContextViewer extends javax.swing.JPanel implements DataConte
"ContextViewer.email=Email",
"ContextViewer.messageFrom=From",
"ContextViewer.messageTo=To",
"ContextViewer.messageOn=On",
})
"ContextViewer.messageOn=On",})
private String msgArtifactToAbbreviatedString(BlackboardArtifact artifact) throws TskCoreException {
StringBuilder sb = new StringBuilder(ARTIFACT_STR_MAX_LEN);
@ -391,11 +393,11 @@ public final class ContextViewer extends javax.swing.JPanel implements DataConte
* Looks up specified attribute in the given map and, if found, appends its
* value to the given string builder.
*
* @param sb String builder to append to.
* @param attribType Attribute type to look for.
* @param sb String builder to append to.
* @param attribType Attribute type to look for.
* @param attributesMap Attributes map.
* @param prependStr Optional string that is prepended before the attribute
* value.
* @param prependStr Optional string that is prepended before the
* attribute value.
*/
private void appendAttributeString(StringBuilder sb, BlackboardAttribute.ATTRIBUTE_TYPE attribType,
Map<BlackboardAttribute.ATTRIBUTE_TYPE, BlackboardAttribute> attributesMap, String prependStr) {
@ -436,6 +438,8 @@ public final class ContextViewer extends javax.swing.JPanel implements DataConte
// Variables declaration - do not modify//GEN-BEGIN:variables
private javax.swing.JButton jSourceGoToResultButton;
private javax.swing.JLabel jSourceLabel;
private javax.swing.JLabel jSourceNameLabel;
private javax.swing.JLabel jSourceTextLabel;
// End of variables declaration//GEN-END:variables

Binary file not shown.

After

Width:  |  Height:  |  Size: 415 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 436 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 247 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 418 B

View File

@ -610,7 +610,7 @@ public class DataContentViewerArtifact extends javax.swing.JPanel implements Dat
* display string.
*
* @param element JSON element to convert
* @param indentStr Starting indentation for the element.
* @param startIndent Starting indentation for the element.
*
* @return A multi-line display string.
*/
@ -634,7 +634,8 @@ public class DataContentViewerArtifact extends javax.swing.JPanel implements Dat
/**
* Converts the given JSON element into string and appends to the given string builder.
*
* @param entry JSON entry to parse
* @param jsonKey
* @param jsonElement
* @param startIndent Starting indentation for the element.
* @param sb String builder to append to.
*/

View File

@ -304,9 +304,6 @@ OpenReportAction.actionPerformed.ReportFileOpenPermissionDeniedMessage=Permissio
PoolNode.createSheet.name.desc=no description
PoolNode.createSheet.name.displayName=Name
PoolNode.createSheet.name.name=Name
PoolNode.createSheet.offset.desc=no description
PoolNode.createSheet.offset.displayName=Starting offset
PoolNode.createSheet.offset.name=Starting offset
PoolNode.createSheet.type.desc=no description
PoolNode.createSheet.type.displayName=Type
PoolNode.createSheet.type.name=Type

View File

@ -1,7 +1,7 @@
/*
* Autopsy Forensic Browser
*
* Copyright 2017-2018 Basis Technology Corp.
* Copyright 2017-2019 Basis Technology Corp.
* Contact: carrier <at> sleuthkit <dot> org
*
* Licensed under the Apache License, Version 2.0 (the "License");
@ -23,6 +23,7 @@ import java.util.Collections;
import java.util.List;
import javax.swing.Action;
import org.openide.util.NbBundle;
import org.sleuthkit.autopsy.casemodule.DeleteDataSourceAction;
import org.sleuthkit.autopsy.casemodule.datasourcesummary.ViewSummaryInformationAction;
import org.sleuthkit.autopsy.coreutils.ContextMenuExtensionPoint;
import org.sleuthkit.autopsy.directorytree.ExportCSVAction;
@ -37,7 +38,7 @@ import org.sleuthkit.datamodel.SpecialDirectory;
* Parent class for special directory types (Local and Virtual)
*/
public abstract class SpecialDirectoryNode extends AbstractAbstractFileNode<SpecialDirectory> {
public SpecialDirectoryNode(SpecialDirectory sd) {
super(sd);
}
@ -68,6 +69,7 @@ public abstract class SpecialDirectoryNode extends AbstractAbstractFileNode<Spec
if (content.isDataSource()) {
actions.add(new ViewSummaryInformationAction(content.getId()));
actions.add(new RunIngestModulesAction(Collections.<Content>singletonList(content)));
actions.add(new DeleteDataSourceAction(content.getId()));
} else {
actions.add(new RunIngestModulesAction(content));
}

View File

@ -106,7 +106,7 @@ final class XRYMessagesFileParser implements XRYFileParser {
/**
* Indicates if the display name of the XRY key is a recognized type.
*
* @param xryKey
* @param name
* @return
*/
public static boolean contains(String name) {
@ -125,7 +125,7 @@ final class XRYMessagesFileParser implements XRYFileParser {
* IllegalArgumentException is thrown. Test all membership with
* contains() before hand.
*
* @param xryKey
* @param name
* @return
*/
public static XryKey fromDisplayName(String name) {
@ -217,7 +217,7 @@ final class XRYMessagesFileParser implements XRYFileParser {
/**
* Indicates if the display name of the XRY key is a recognized type.
*
* @param xryKey
* @param name
* @return
*/
public static boolean contains(String name) {
@ -236,7 +236,7 @@ final class XRYMessagesFileParser implements XRYFileParser {
* IllegalArgumentException is thrown. Test all membership with
* contains() before hand.
*
* @param xryKey
* @param name
* @return
*/
public static XryMetaKey fromDisplayName(String name) {

View File

@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.sleuthkit.autopsy.coreutils;
package org.sleuthkit.autopsy.exceptions;
import java.util.logging.Filter;
import java.util.logging.Handler;
@ -26,6 +26,9 @@ import java.util.logging.SimpleFormatter;
import javax.swing.JOptionPane;
import org.openide.util.lookup.ServiceProvider;
import org.netbeans.core.NbErrorManager;
import org.sleuthkit.autopsy.coreutils.Logger;
import org.sleuthkit.autopsy.coreutils.MessageNotifyUtil;
import org.sleuthkit.autopsy.coreutils.Version;
/**
* Replaces default NetBeans exception handler. Displays messages in a dialog.

View File

@ -44,7 +44,7 @@ FileSearchPanel.hashSetCheckbox.text=Hash Set:
FileSearchPanel.tagsCheckbox.text=Tag:
FileSearchPanel.interestingItemsCheckbox.text=Interesting Item:
FileSearchPanel.scoreCheckbox.text=Has Score:
FileSearchPanel.exifCheckbox.text=Must contain EXIF data
FileSearchPanel.exifCheckbox.text=Possibly User Created
FileSearchPanel.notableCheckbox.text=Must have been tagged as notable
FileSearchPanel.objectsCheckbox.text=Object Detected:
ResultsPanel.currentPageLabel.text=Page: -

View File

@ -150,7 +150,7 @@ FileSearchPanel.hashSetCheckbox.text=Hash Set:
FileSearchPanel.tagsCheckbox.text=Tag:
FileSearchPanel.interestingItemsCheckbox.text=Interesting Item:
FileSearchPanel.scoreCheckbox.text=Has Score:
FileSearchPanel.exifCheckbox.text=Must contain EXIF data
FileSearchPanel.exifCheckbox.text=Possibly User Created
FileSearchPanel.notableCheckbox.text=Must have been tagged as notable
FileSearchPanel.objectsCheckbox.text=Object Detected:
FileSorter.SortingMethod.datasource.displayName=Data Source

View File

@ -47,7 +47,7 @@ final class FileSearchData {
UNIQUE(0, 1, Bundle.FileSearchData_Frequency_unique_displayName()),
RARE(1, 10, Bundle.FileSearchData_Frequency_rare_displayName()),
COMMON(2, 100, Bundle.FileSearchData_Frequency_common_displayName()),
VERY_COMMON(3, 0, Bundle.FileSearchData_Frequency_common_displayName()),
VERY_COMMON(3, 0, Bundle.FileSearchData_Frequency_verycommon_displayName()),
KNOWN(4, 0, Bundle.FileSearchData_Frequency_known_displayName()),
UNKNOWN(5, 0, Bundle.FileSearchData_Frequency_unknown_displayName());

View File

@ -1,7 +1,7 @@
/*
* Autopsy Forensic Browser
*
* Copyright 2019 Basis Technology Corp.
* Copyright 2019-2020 Basis Technology Corp.
* Contact: carrier <at> sleuthkit <dot> org
*
* Licensed under the Apache License, Version 2.0 (the "License");
@ -22,21 +22,17 @@ import org.sleuthkit.autopsy.centralrepository.datamodel.CorrelationAttributeIns
import org.sleuthkit.autopsy.centralrepository.datamodel.CorrelationAttributeNormalizationException;
import org.sleuthkit.autopsy.centralrepository.datamodel.EamDb;
import org.sleuthkit.autopsy.centralrepository.datamodel.EamDbException;
import org.sleuthkit.autopsy.coreutils.Logger;
import org.sleuthkit.autopsy.filequery.FileSearchData.FileSize;
import org.sleuthkit.autopsy.filequery.FileSearchData.FileType;
import org.sleuthkit.autopsy.filequery.FileSearchData.Frequency;
import org.sleuthkit.autopsy.filequery.FileSearchData.Score;
import org.sleuthkit.datamodel.AbstractFile;
import org.sleuthkit.datamodel.DataSource;
import org.sleuthkit.datamodel.SleuthkitCase;
import org.sleuthkit.datamodel.TagName;
import org.sleuthkit.datamodel.TskCoreException;
import java.util.ArrayList;
import java.util.List;
import java.util.logging.Level;
import java.util.stream.Collectors;
import org.openide.util.NbBundle;
import org.sleuthkit.datamodel.BlackboardArtifact;
@ -48,8 +44,6 @@ import org.sleuthkit.datamodel.TskData;
*/
class FileSearchFiltering {
private final static Logger logger = Logger.getLogger(FileSearchFiltering.class.getName());
/**
* Run the given filters to get a list of matching files.
*
@ -61,18 +55,9 @@ class FileSearchFiltering {
* @return
*/
static List<ResultFile> runQueries(List<FileFilter> filters, SleuthkitCase caseDb, EamDb centralRepoDb) throws FileSearchException {
if (caseDb == null) {
throw new FileSearchException("Case DB parameter is null"); // NON-NLS
}
// Record the selected filters
String filterStr = "";
for (FileFilter filter : filters) {
filterStr += " " + filter.getDesc() + "\n";
}
logger.log(Level.INFO, "Running filters:\n{0}", filterStr);
// Combine all the SQL queries from the filters into one query
String combinedQuery = "";
for (FileFilter filter : filters) {
@ -112,8 +97,6 @@ class FileSearchFiltering {
private static List<ResultFile> getResultList(List<FileFilter> filters, String combinedQuery, SleuthkitCase caseDb, EamDb centralRepoDb) throws TskCoreException, FileSearchException {
// Get all matching abstract files
List<ResultFile> resultList = new ArrayList<>();
logger.log(Level.INFO, "Running SQL query: {0}", combinedQuery);
List<AbstractFile> sqlResults = caseDb.findAllFilesWhere(combinedQuery);
// If there are no results, return now

View File

@ -404,15 +404,6 @@
<Connection code="new DefaultListModel&lt;ParentSearchTerm&gt;()" type="code"/>
</Property>
<Property name="enabled" type="boolean" value="false"/>
<Property name="maximumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="null"/>
</Property>
<Property name="minimumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[0, 30]"/>
</Property>
<Property name="preferredSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[0, 30]"/>
</Property>
<Property name="visibleRowCount" type="int" value="4"/>
</Properties>
<Events>
@ -457,12 +448,6 @@
<Connection code="new DefaultListModel&lt;String&gt;()" type="code"/>
</Property>
<Property name="enabled" type="boolean" value="false"/>
<Property name="minimumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[0, 30]"/>
</Property>
<Property name="preferredSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[0, 30]"/>
</Property>
<Property name="visibleRowCount" type="int" value="3"/>
</Properties>
<AuxValues>
@ -573,12 +558,6 @@
<Connection code="new DefaultListModel&lt;String&gt;()" type="code"/>
</Property>
<Property name="enabled" type="boolean" value="false"/>
<Property name="minimumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[0, 30]"/>
</Property>
<Property name="preferredSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[0, 30]"/>
</Property>
<Property name="visibleRowCount" type="int" value="2"/>
</Properties>
<AuxValues>
@ -631,12 +610,6 @@
<Connection code="new DefaultListModel&lt;String&gt;()" type="code"/>
</Property>
<Property name="enabled" type="boolean" value="false"/>
<Property name="minimumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[0, 30]"/>
</Property>
<Property name="preferredSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[0, 30]"/>
</Property>
<Property name="visibleRowCount" type="int" value="2"/>
</Properties>
<AuxValues>

View File

@ -1328,9 +1328,6 @@ final class FileSearchPanel extends javax.swing.JPanel implements ActionListener
parentList.setModel(new DefaultListModel<ParentSearchTerm>());
parentList.setEnabled(false);
parentList.setMaximumSize(null);
parentList.setMinimumSize(new java.awt.Dimension(0, 30));
parentList.setPreferredSize(new java.awt.Dimension(0, 30));
parentList.setVisibleRowCount(4);
parentList.addListSelectionListener(new javax.swing.event.ListSelectionListener() {
public void valueChanged(javax.swing.event.ListSelectionEvent evt) {
@ -1366,8 +1363,6 @@ final class FileSearchPanel extends javax.swing.JPanel implements ActionListener
hashSetList.setModel(new DefaultListModel<String>());
hashSetList.setEnabled(false);
hashSetList.setMinimumSize(new java.awt.Dimension(0, 30));
hashSetList.setPreferredSize(new java.awt.Dimension(0, 30));
hashSetList.setVisibleRowCount(3);
hashSetScrollPane.setViewportView(hashSetList);
@ -1454,8 +1449,6 @@ final class FileSearchPanel extends javax.swing.JPanel implements ActionListener
objectsList.setModel(new DefaultListModel<String>());
objectsList.setEnabled(false);
objectsList.setMinimumSize(new java.awt.Dimension(0, 30));
objectsList.setPreferredSize(new java.awt.Dimension(0, 30));
objectsList.setVisibleRowCount(2);
objectsScrollPane.setViewportView(objectsList);
@ -1487,8 +1480,6 @@ final class FileSearchPanel extends javax.swing.JPanel implements ActionListener
interestingItemsList.setModel(new DefaultListModel<String>());
interestingItemsList.setEnabled(false);
interestingItemsList.setMinimumSize(new java.awt.Dimension(0, 30));
interestingItemsList.setPreferredSize(new java.awt.Dimension(0, 30));
interestingItemsList.setVisibleRowCount(2);
interestingItemsScrollPane.setViewportView(interestingItemsList);

View File

@ -290,11 +290,11 @@
</DimensionLayout>
<DimensionLayout dim="1">
<Group type="103" groupAlignment="0" attributes="0">
<EmptySpace min="0" pref="221" max="32767" attributes="0"/>
<EmptySpace min="0" pref="68" max="32767" attributes="0"/>
<Group type="103" rootIndex="1" groupAlignment="0" attributes="0">
<Group type="102" alignment="1" attributes="0">
<EmptySpace min="-2" pref="0" max="-2" attributes="0"/>
<Component id="instancesScrollPane" pref="221" max="32767" attributes="0"/>
<Component id="instancesScrollPane" max="32767" attributes="0"/>
</Group>
</Group>
</Group>
@ -331,9 +331,6 @@
<Property name="cellRenderer" type="javax.swing.ListCellRenderer" editor="org.netbeans.modules.form.RADConnectionPropertyEditor">
<Connection code="new InstancesCellRenderer()" type="code"/>
</Property>
<Property name="preferredSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[0, 50]"/>
</Property>
<Property name="visibleRowCount" type="int" value="2"/>
</Properties>
<AuxValues>

View File

@ -146,14 +146,22 @@ public class ResultsPanel extends javax.swing.JPanel {
*/
synchronized void populateInstancesList() {
SwingUtilities.invokeLater(() -> {
instancesList.removeListSelectionListener(listener);
instancesListModel.removeAllElements();
for (AbstractFile file : getInstancesForSelected()) {
instancesListModel.addElement(file);
}
instancesList.addListSelectionListener(listener);
if (!instancesListModel.isEmpty()) {
instancesList.setSelectedIndex(0);
List<AbstractFile> files = getInstancesForSelected();
if (files.isEmpty()) {
//if there are no files currently remove the current items without removing listener to cause content viewer to reset
instancesListModel.removeAllElements();
} else {
//remove listener so content viewer node is not set multiple times
instancesList.removeListSelectionListener(listener);
instancesListModel.removeAllElements();
for (AbstractFile file : files) {
instancesListModel.addElement(file);
}
//add listener back to allow selection of first index to cause content viewer node to be set
instancesList.addListSelectionListener(listener);
if (!instancesListModel.isEmpty()) {
instancesList.setSelectedIndex(0);
}
}
});
}
@ -488,7 +496,6 @@ public class ResultsPanel extends javax.swing.JPanel {
instancesList.setModel(instancesListModel);
instancesList.setSelectionMode(javax.swing.ListSelectionModel.SINGLE_SELECTION);
instancesList.setCellRenderer(new InstancesCellRenderer());
instancesList.setPreferredSize(new java.awt.Dimension(0, 50));
instancesList.setVisibleRowCount(2);
instancesScrollPane.setViewportView(instancesList);
@ -502,11 +509,11 @@ public class ResultsPanel extends javax.swing.JPanel {
);
instancesPanelLayout.setVerticalGroup(
instancesPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGap(0, 221, Short.MAX_VALUE)
.addGap(0, 68, Short.MAX_VALUE)
.addGroup(instancesPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(javax.swing.GroupLayout.Alignment.TRAILING, instancesPanelLayout.createSequentialGroup()
.addGap(0, 0, 0)
.addComponent(instancesScrollPane, javax.swing.GroupLayout.DEFAULT_SIZE, 221, Short.MAX_VALUE)))
.addComponent(instancesScrollPane, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)))
);
resultsSplitPane.setRightComponent(instancesPanel);

View File

@ -85,6 +85,8 @@ public final class GeolocationTopComponent extends TopComponent {
// This is the hardcoded report name from KMLReport.java
private static final String REPORT_KML = "ReportKML.kml";
private boolean mapInitalized = false;
@Messages({
"GLTopComponent_name=Geolocation",
@ -194,20 +196,26 @@ public final class GeolocationTopComponent extends TopComponent {
@Override
public void open() {
super.open();
mapPanel.clearWaypoints();
geoFilterPanel.clearDataSourceList();
geoFilterPanel.updateDataSourceList();
try {
mapPanel.initMap();
} catch (GeoLocationDataException ex) {
JOptionPane.showMessageDialog(this,
Bundle.GeolocationTC_connection_failure_message(),
Bundle.GeolocationTC_connection_failure_message_title(),
JOptionPane.ERROR_MESSAGE);
MessageNotifyUtil.Notify.error(
Bundle.GeolocationTC_connection_failure_message_title(),
Bundle.GeolocationTC_connection_failure_message());
logger.log(Level.SEVERE, ex.getMessage(), ex);
return; // Doen't set the waypoints.
// Let's make sure we only do this on the first open
if (!mapInitalized) {
try {
mapPanel.initMap();
mapInitalized = true;
} catch (GeoLocationDataException ex) {
JOptionPane.showMessageDialog(this,
Bundle.GeolocationTC_connection_failure_message(),
Bundle.GeolocationTC_connection_failure_message_title(),
JOptionPane.ERROR_MESSAGE);
MessageNotifyUtil.Notify.error(
Bundle.GeolocationTC_connection_failure_message_title(),
Bundle.GeolocationTC_connection_failure_message());
logger.log(Level.SEVERE, ex.getMessage(), ex);
return; // Doen't set the waypoints.
}
}
mapPanel.setWaypoints(new ArrayList<>());
updateWaypoints();
@ -288,7 +296,7 @@ public final class GeolocationTopComponent extends TopComponent {
DateFormat dateFormat = new SimpleDateFormat("MM-dd-yyyy-HH-mm-ss", Locale.US);
Date date = new Date();
String dateNoTime = dateFormat.format(date);
String reportPath = String.format(REPORT_PATH_FMT_STR, currentCase.getReportDirectory(), currentCase.getDisplayName(), "Goggle Earth KML", dateNoTime);
String reportPath = String.format(REPORT_PATH_FMT_STR, currentCase.getReportDirectory(), currentCase.getDisplayName(), "Google Earth KML", dateNoTime);
// Create the root reports directory.
try {
FileUtil.createFolder(new File(reportPath));
@ -446,7 +454,7 @@ public final class GeolocationTopComponent extends TopComponent {
private class WaypointCallBack implements WaypointFilterQueryCallBack {
@Override
public void process(List<Waypoint> waypoints) {
public void process(final List<Waypoint> waypoints) {
// Make sure that the waypoints are added to the map panel in
// the correct thread.
SwingUtilities.invokeLater(new Runnable() {
@ -455,13 +463,16 @@ public final class GeolocationTopComponent extends TopComponent {
// If the list is empty, tell the user and do not change
// the visible waypoints.
if (waypoints == null || waypoints.isEmpty()) {
mapPanel.clearWaypoints();
JOptionPane.showMessageDialog(GeolocationTopComponent.this,
Bundle.GeoTopComponent_no_waypoints_returned_Title(),
Bundle.GeoTopComponent_no_waypoints_returned_mgs(),
JOptionPane.INFORMATION_MESSAGE);
setWaypointLoading(false);
geoFilterPanel.setEnabled(true);
return;
}
mapPanel.clearWaypoints();
mapPanel.setWaypoints(MapWaypoint.getWaypoints(waypoints));
setWaypointLoading(false);
geoFilterPanel.setEnabled(true);

View File

@ -256,7 +256,7 @@ final class MBTilesTileFactory extends TileFactory {
/**
* An inner class which actually loads the tiles. Used by the thread queue.
* Subclasses can override this via {@link #createTileRunner(Tile)} if
* Subclasses can override this via createTileRunner(Tile) if
* necessary.
*/
private class TileRunner implements Runnable {

View File

@ -0,0 +1,115 @@
/*
* Autopsy Forensic Browser
*
* Copyright 2019 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.geolocation;
import java.awt.Cursor;
import java.awt.Point;
import java.awt.event.MouseEvent;
import java.awt.geom.Point2D;
import javax.swing.SwingUtilities;
import javax.swing.event.MouseInputAdapter;
import org.jxmapviewer.JXMapViewer;
/**
* MouseInputListener for panning a JXMapViewer
*
* This class is adapted from org.jxmapviewer.input.PanMouseInputListener.
*/
final class MapPanMouseInputListener extends MouseInputAdapter {
private Point prev;
private final JXMapViewer viewer;
private Cursor priorCursor;
private boolean dragging = false;
/**
* Construct a new listener.
*
* @param viewer
*/
MapPanMouseInputListener(JXMapViewer viewer) {
this.viewer = viewer;
}
@Override
public void mousePressed(MouseEvent evt) {
if (!SwingUtilities.isLeftMouseButton(evt)) {
return;
}
if (!viewer.isPanningEnabled()) {
return;
}
// Store the current click point and current cursor
prev = evt.getPoint();
priorCursor = viewer.getCursor();
}
@Override
public void mouseDragged(MouseEvent evt) {
if (!SwingUtilities.isLeftMouseButton(evt)) {
return;
}
if (!viewer.isPanningEnabled()) {
return;
}
// If the map wasn't previously being dragged, set the cursor
if (!dragging) {
viewer.setCursor(Cursor.getPredefinedCursor(Cursor.MOVE_CURSOR));
dragging = true;
}
// Figure out the new map center
Point current = evt.getPoint();
double x = viewer.getCenter().getX();
double y = viewer.getCenter().getY();
if (prev != null) {
x += prev.x - current.x;
y += prev.y - current.y;
}
int maxHeight = (int) (viewer.getTileFactory().getMapSize(viewer.getZoom()).getHeight() * viewer
.getTileFactory().getTileSize(viewer.getZoom()));
if (y > maxHeight) {
y = maxHeight;
}
prev = current;
viewer.setCenter(new Point2D.Double(x, y));
viewer.repaint();
}
@Override
public void mouseReleased(MouseEvent evt) {
if (!SwingUtilities.isLeftMouseButton(evt)) {
return;
}
prev = null;
// If we were dragging set the cursor back
if (dragging) {
viewer.setCursor(priorCursor);
dragging = false;
}
}
}

View File

@ -26,7 +26,6 @@ import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.ComponentAdapter;
import java.awt.event.ComponentEvent;
import java.awt.event.MouseEvent;
import java.awt.geom.Point2D;
import java.awt.image.BufferedImage;
import java.beans.PropertyChangeEvent;
@ -54,7 +53,6 @@ import org.jxmapviewer.JXMapViewer;
import org.jxmapviewer.OSMTileFactoryInfo;
import org.jxmapviewer.VirtualEarthTileFactoryInfo;
import org.jxmapviewer.input.CenterMapListener;
import org.jxmapviewer.input.PanMouseInputListener;
import org.jxmapviewer.input.ZoomMouseWheelListenerCursor;
import org.jxmapviewer.viewer.DefaultTileFactory;
import org.jxmapviewer.viewer.GeoPosition;
@ -140,6 +138,8 @@ final public class MapPanel extends javax.swing.JPanel {
}
}
});
}
/**
@ -172,7 +172,7 @@ final public class MapPanel extends javax.swing.JPanel {
mapViewer.setTileFactory(tileFactory);
// Add Mouse interactions
MouseInputListener mia = new PanMouseInputListener(mapViewer);
MouseInputListener mia = new MapPanMouseInputListener(mapViewer);
mapViewer.addMouseListener(mia);
mapViewer.addMouseMotionListener(mia);
@ -279,7 +279,7 @@ final public class MapPanel extends javax.swing.JPanel {
/**
* Create the TileFactoryInfo for OSM zip File
*
* @param zipPath Path to zip file.
* @param path Path to zip file.
*
* @return TileFactoryInfo for zip file.
*
@ -332,6 +332,11 @@ final public class MapPanel extends javax.swing.JPanel {
*/
void clearWaypoints() {
waypointTree = null;
currentlySelectedWaypoint = null;
if (currentPopup != null) {
currentPopup.hide();
}
mapViewer.repaint();
}
/**
@ -525,7 +530,7 @@ final public class MapPanel extends javax.swing.JPanel {
}
/**
* Called when the resize event has completed\timed out
* Called when the resize event has completed or timed out
*/
public abstract void resizeTimedOut();
}

View File

@ -125,6 +125,7 @@ public final class Route {
/**
* Get the route start point.
*
* @param artifact
* @param attributeMap Map of artifact attributes for this waypoint.
*
* An exception will be thrown if longitude or latitude is null.

View File

@ -187,7 +187,7 @@ public class Waypoint {
/**
* Gets the label for this waypoint.
*
* @param artifact BlackboardArtifact for waypoint
* @param attributeMap Attributes for waypoint
*
* @return Returns a label for the waypoint, or empty string if no label was
* found.
@ -232,7 +232,7 @@ public class Waypoint {
* will not include attributes that the Waypoint interfact has get functions
* for.
*
* @param artifact Blackboard artifact to get attributes\properties from
* @param attributeMap Attributes for the given artifact
*
* @return A List of Waypoint.Property objects
*

View File

@ -56,7 +56,8 @@ public final class WaypointBuilder {
final static String GEO_ARTIFACT_WITH_DATA_SOURCES_QUERY
= "SELECT blackboard_attributes.artifact_id "
+ "FROM blackboard_attributes, blackboard_artifacts "
+ "WHERE blackboard_attributes.attribute_type_id IN(%d, %d) "
+ "WHERE blackboard_attributes.artifact_id = blackboard_artifacts.artifact_id "
+ "AND blackboard_attributes.attribute_type_id IN(%d, %d) "
+ "AND data_source_obj_id IN (%s)"; //NON-NLS
// Select will return the "most recent" timestamp from all waypoings
@ -469,6 +470,18 @@ public final class WaypointBuilder {
* @return SQL SELECT statement
*/
static private String buildQueryForWaypointsWOTimeStamps(List<DataSource> dataSources) {
// SELECT_WO_TIMESTAMP
// SELECT DISTINCT artifact_id, artifact_type_id
// FROM blackboard_attributes
// WHERE artifact_id NOT IN (%s)
// AND artifact_id IN (%s)
// GEO_ARTIFACT_QUERY_ID_ONLY
// SELECT artifact_id
// FROM blackboard_attributes
// WHERE attribute_type_id IN (%d, %d)
return String.format(SELECT_WO_TIMESTAMP,
String.format(GEO_ARTIFACT_QUERY_ID_ONLY,
BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DATETIME.getTypeID(),
@ -502,16 +515,26 @@ public final class WaypointBuilder {
String mostRecentQuery = "";
if (!showAll && cntDaysFromRecent > 0) {
mostRecentQuery = String.format("AND value_int64 > (%s)", //NON-NLS
String.format(MOST_RECENT_TIME,
cntDaysFromRecent,
BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DATETIME.getTypeID(),
BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DATETIME_CREATED.getTypeID(),
getWaypointListQuery(dataSources)
));
// MOST_RECENT_TIME
// SELECT MAX(value_int64) - (%d * 86400)
// FROM blackboard_attributes
// WHERE attribute_type_id IN(%d, %d)
// AND artifact_id
// IN ( %s )
//
mostRecentQuery = String.format("AND value_int64 > (%s)", //NON-NLS
String.format(MOST_RECENT_TIME,
cntDaysFromRecent,
BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DATETIME.getTypeID(),
BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DATETIME_CREATED.getTypeID(),
getWaypointListQuery(dataSources)
));
}
// This givens us all artifact_ID that have time stamp
// GEO_ARTIFACT_QUERY
// SELECT artifact_id, artifact_type_id
// FROM blackboard_attributes
// WHERE attribute_type_id IN (%d, %d)
String query = String.format(GEO_ARTIFACT_QUERY,
BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DATETIME.getTypeID(),
BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DATETIME_CREATED.getTypeID());
@ -542,6 +565,10 @@ public final class WaypointBuilder {
static private String getWaypointListQuery(List<DataSource> dataSources) {
if (dataSources == null || dataSources.isEmpty()) {
// GEO_ARTIFACT_QUERY
// SELECT artifact_id, artifact_type_id
// FROM blackboard_attributes
// WHERE attribute_type_id IN (%d, %d)
return String.format(GEO_ARTIFACT_QUERY,
BlackboardAttribute.ATTRIBUTE_TYPE.TSK_GEO_LATITUDE.getTypeID(),
BlackboardAttribute.ATTRIBUTE_TYPE.TSK_GEO_LATITUDE_START.getTypeID());

View File

@ -16,7 +16,6 @@ EmbeddedFileExtractorIngestModule.ArchiveExtractor.isZipBombCheck.warnMsg=Possib
EmbeddedFileExtractorIngestModule.ArchiveExtractor.isZipBombCheck.warnDetails=Compression ratio is {0}, skipping items in {1}.
EmbeddedFileExtractorIngestModule.ArchiveExtractor.unpack.warnMsg.zipBomb=Possible ZIP bomb detected: {0}
EmbeddedFileExtractorIngestModule.ArchiveExtractor.unpack.warnDetails.zipBomb=The archive is {0} levels deep, skipping processing of {1}
EmbeddedFileExtractorIngestModule.ArchiveExtractor.unpack.unknownPath.msg=Unknown item path in archive: {0}, will use: {1}
EmbeddedFileExtractorIngestModule.ArchiveExtractor.unpack.notEnoughDiskSpace.msg=Not enough disk space to unpack archive item: {0}, {1}
EmbeddedFileExtractorIngestModule.ArchiveExtractor.unpack.notEnoughDiskSpace.details=The archive item is too large to unpack, skipping unpacking this item.
EmbeddedFileExtractorIngestModule.ArchiveExtractor.unpack.errUnpacking.msg=Error unpacking {0}

View File

@ -28,7 +28,6 @@ EmbeddedFileExtractorIngestModule.ArchiveExtractor.isZipBombCheck.warnMsg=\u30a2
EmbeddedFileExtractorIngestModule.ArchiveExtractor.isZipBombCheck.warnDetails=\u5727\u7e2e\u7387\u306f {0} \u3067\u3059\u3002{1} \u306e\u9805\u76ee\u3092\u30b9\u30ad\u30c3\u30d7\u3057\u307e\u3059\u3002
EmbeddedFileExtractorIngestModule.ArchiveExtractor.unpack.warnMsg.zipBomb=ZIP\u7206\u5f3e\u304c\u691c\u51fa\u3055\u308c\u305f\u53ef\u80fd\u6027\u304c\u3042\u308a\u307e\u3059: {0}
EmbeddedFileExtractorIngestModule.ArchiveExtractor.unpack.warnDetails.zipBomb=\u30a2\u30fc\u30ab\u30a4\u30d6\u306f {0} \u30ec\u30d9\u30eb\u306e\u6df1\u3055\u3067\u3059\u3002{1} \u306e\u51e6\u7406\u3092\u30b9\u30ad\u30c3\u30d7\u3057\u307e\u3059
EmbeddedFileExtractorIngestModule.ArchiveExtractor.unpack.unknownPath.msg=\u30a2\u30fc\u30ab\u30a4\u30d6\u306e\u4e0d\u660e\u306a\u9805\u76ee\u30d1\u30b9: {0}\u3001\u6b21\u3092\u4f7f\u7528\u3057\u307e\u3059: {1}
EmbeddedFileExtractorIngestModule.ArchiveExtractor.unpack.notEnoughDiskSpace.msg=\u30a2\u30fc\u30ab\u30a4\u30d6\u9805\u76ee\u3092\u958b\u5c01\u3059\u308b\u305f\u3081\u306e\u5341\u5206\u306a\u30c7\u30a3\u30b9\u30af\u9818\u57df\u304c\u3042\u308a\u307e\u305b\u3093: {0}\u3001{1}
EmbeddedFileExtractorIngestModule.ArchiveExtractor.unpack.notEnoughDiskSpace.details=\u30a2\u30fc\u30ab\u30a4\u30d6\u9805\u76ee\u304c\u5927\u304d\u3059\u304e\u3067\u958b\u5c01\u3067\u304d\u307e\u305b\u3093\u3002\u3053\u306e\u9805\u76ee\u306e\u958b\u5c01\u3092\u30b9\u30ad\u30c3\u30d7\u3057\u307e\u3059\u3002
EmbeddedFileExtractorIngestModule.ArchiveExtractor.unpack.errUnpacking.msg={0} \u306e\u958b\u5c01\u4e2d\u306b\u30a8\u30e9\u30fc\u304c\u767a\u751f\u3057\u307e\u3057\u305f

View File

@ -449,10 +449,6 @@ class SevenZipExtractor {
} else {
pathInArchive = "/" + useName;
}
String msg = NbBundle.getMessage(SevenZipExtractor.class,
"EmbeddedFileExtractorIngestModule.ArchiveExtractor.unpack.unknownPath.msg",
getArchiveFilePath(archiveFile), pathInArchive);
logger.log(Level.WARNING, msg);
}
return pathInArchive;
}
@ -1196,6 +1192,7 @@ class SevenZipExtractor {
*
* @param parent
* @param tokenPath
* @param tokenPathBytes
*
* @return
*/

View File

@ -1,5 +1,6 @@
CannotRunFileTypeDetection=Cannot run file type detection.
ExifParserFileIngestModule.indexError.message=Failed to post EXIF Metadata artifact(s).
ExifParserFileIngestModule.userContent.description=EXIF metadata exists for this file.
OpenIDE-Module-Display-Category=Ingest Module
OpenIDE-Module-Long-Description=Exif metadata ingest module. \n\nThe ingest module analyzes image files, extracts Exif information and posts the Exif data as results.
OpenIDE-Module-Name=ExifParser

View File

@ -49,6 +49,7 @@ import org.sleuthkit.datamodel.AbstractFile;
import org.sleuthkit.datamodel.Blackboard;
import org.sleuthkit.datamodel.BlackboardArtifact;
import static org.sleuthkit.datamodel.BlackboardArtifact.ARTIFACT_TYPE.TSK_METADATA_EXIF;
import static org.sleuthkit.datamodel.BlackboardArtifact.ARTIFACT_TYPE.TSK_USER_CONTENT_SUSPECTED;
import org.sleuthkit.datamodel.BlackboardAttribute;
import static org.sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DATETIME_CREATED;
import static org.sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DEVICE_MAKE;
@ -130,6 +131,7 @@ public final class ExifParserFileIngestModule implements FileIngestModule {
return processFile(content);
}
@Messages({"ExifParserFileIngestModule.userContent.description=EXIF metadata exists for this file."})
private ProcessResult processFile(AbstractFile file) {
try (BufferedInputStream bin = new BufferedInputStream(new ReadContentInputStream(file));) {
@ -193,11 +195,13 @@ public final class ExifParserFileIngestModule implements FileIngestModule {
// Create artifact if it doesn't already exist.
if (!blackboard.artifactExists(file, TSK_METADATA_EXIF, attributes)) {
BlackboardArtifact bba = file.newArtifact(TSK_METADATA_EXIF);
BlackboardArtifact bba2 = file.newArtifact(TSK_USER_CONTENT_SUSPECTED);
bba.addAttributes(attributes);
bba2.addAttribute(new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DESCRIPTION, MODULE_NAME, Bundle.ExifParserFileIngestModule_userContent_description()));
try {
// index the artifact for keyword search
blackboard.postArtifact(bba, MODULE_NAME);
blackboard.postArtifact(bba2, MODULE_NAME);
} catch (Blackboard.BlackboardException ex) {
logger.log(Level.SEVERE, "Unable to index blackboard artifact " + bba.getArtifactID(), ex); //NON-NLS
MessageNotifyUtil.Notify.error(

View File

@ -254,10 +254,10 @@ public class FileTypeDetector {
} else {
/*
* If the file was marked as an octet stream and the extension is .txt, try to detect a text
* encoding with Decodetect.
* encoding
*/
if (file.getNameExtension().equals("txt")) {
Charset detectedCharset = TextFileExtractor.getEncoding(file);
Charset detectedCharset = new TextFileExtractor(file).getEncoding();
if (detectedCharset != TextFileExtractor.UNKNOWN_CHARSET) {
mimeType = MimeTypes.PLAIN_TEXT;
}

View File

@ -3,7 +3,7 @@ PlasoIngestModule.artifact.progress=Adding events to case: {0}
PlasoIngestModule.bad.imageFile=Cannot find image file name and path
PlasoIngestModule.completed=Plaso Processing Completed
PlasoIngestModule.create.artifacts.cancelled=Cancelled Plaso Artifact Creation
PlasoIngestModule.dataSource.not.an.image=Datasource is not an Image.
PlasoIngestModule.dataSource.not.an.image=Skipping non-disk image datasource
PlasoIngestModule.error.creating.output.dir=Error creating Plaso module output directory.
PlasoIngestModule.error.running.log2timeline=Error running log2timeline, see log file.
PlasoIngestModule.error.running.psort=Error running Psort, see log file.
@ -11,7 +11,7 @@ PlasoIngestModule.event.datetime=Event Date Time
PlasoIngestModule.event.description=Event Description
PlasoIngestModule.exception.posting.artifact=Exception Posting artifact.
PlasoIngestModule.executable.not.found=Plaso Executable Not Found.
PlasoIngestModule.has.run=Plaso Plugin has been run.
PlasoIngestModule.has.run=Plaso
PlasoIngestModule.info.empty.database=Plaso database was empty.
PlasoIngestModule.log2timeline.cancelled=Log2timeline run was canceled
PlasoIngestModule.psort.cancelled=psort run was canceled

View File

@ -117,6 +117,7 @@ public final class KMLReport implements GeneralReportModule {
*
* @param baseReportDir path to save the report
* @param progressPanel panel to update the report's progress
* @param waypointList
*/
@Messages({
"KMLReport.unableToExtractPhotos=Could not extract photo information.",
@ -524,10 +525,8 @@ public final class KMLReport implements GeneralReportModule {
*
* @param startLatitude Starting latitude
* @param startLongitude Starting longitude
* @param startAltitude Starting altitude. Currently ignored.
* @param stopLatitude Ending latitude
* @param stopLongitude Ending longitude
* @param stopAltitude Ending altitude. Currently ignored.
*
* @return the Line as an Element
*/

View File

@ -85,14 +85,14 @@ public class TextExtractorFactory {
* @param content AbstractFile content
* @param context Lookup containing extractor configurations
*
* @return
* @return List of all extractors in priority order. Not all will support the passed in content. @@@ PERHAPS ONLY SUPPORTED SHOULD BE RETURNED
*/
private static List<TextExtractor> getFileExtractors(AbstractFile content, Lookup context) {
List<TextExtractor> fileExtractors = Arrays.asList(
new TextFileExtractor(content),
new HtmlTextExtractor(content),
new SqliteTextExtractor(content),
new TikaTextExtractor(content));
new TikaTextExtractor(content)); /// This should go last to ensure the more specific ones are picked first.
fileExtractors.forEach((fileExtractor) -> {
fileExtractor.setExtractionSettings(context);

View File

@ -31,17 +31,24 @@ import java.nio.charset.CharsetEncoder;
import java.nio.charset.StandardCharsets;
import java.nio.charset.UnsupportedCharsetException;
import java.util.List;
import java.util.logging.Level;
import org.apache.tika.parser.txt.CharsetDetector;
import org.apache.tika.parser.txt.CharsetMatch;
import org.sleuthkit.autopsy.coreutils.Logger;
import org.sleuthkit.datamodel.AbstractFile;
import org.sleuthkit.datamodel.Content;
import org.sleuthkit.datamodel.ReadContentInputStream;
import org.sleuthkit.datamodel.TskCoreException;
/**
* Extract text from text files
* A TextExtractor that is used to extract text from a text file.
*/
public final class TextFileExtractor implements TextExtractor {
public static Charset UNKNOWN_CHARSET = new Charset("unknown", null) {
/*
* The char set returned if a text file extractor fails to detect the
* encoding of the file from which it is extracting text.
*/
public static final Charset UNKNOWN_CHARSET = new Charset("unknown", null) {
@Override
public boolean contains(Charset cs) {
return false;
@ -59,33 +66,45 @@ public final class TextFileExtractor implements TextExtractor {
};
// This value will be used as a threshold for determining which encoding
// detection library to use. If Tika's own confidence is at least
// MIN_MATCH_CONFIDENCE, Tika's result will be used for decoding.
// detection library to use. If CharsetDetector's own confidence is at least
// MIN_MATCH_CONFIDENCE, CharsetDetector's result will be used for decoding.
// Otherwise, Decodetect will be used.
static final private int MIN_TIKA_MATCH_CONFIDENCE = 35;
//
// Note: We initially used a confidence of 35, but it was causing some
// Chrome Cache files to get flagged as UTF-16 with confidence 40.
// These files had a small amount of binary data and then ASCII.
static final private int MIN_CHARSETDETECT_MATCH_CONFIDENCE = 41;
// This value determines whether we will consider Decodetect's top-scoring
// result a legitimate match or if we will disregard its findings
// result a legitimate match or if we will disregard its findings.
//
// Possible values are 0 to 1, inclusive
// Possible values are 0 to 1, inclusive.
static final private double MIN_DECODETECT_MATCH_CONFIDENCE = 0.4;
private static final Logger logger = Logger.getLogger(SqliteTextExtractor.class.getName());
private final AbstractFile file;
private Charset encoding = null;
/**
* Constructs a TextExtractor that is used to extract text from a text file.
*
* @param file The file.
*/
public TextFileExtractor(AbstractFile file) {
this.file = file;
}
@Override
public Reader getReader() {
Charset encoding = getEncoding(file);
if (encoding.equals(UNKNOWN_CHARSET)) {
encoding = StandardCharsets.UTF_8;
Charset enc = getEncoding();
if (enc.equals(UNKNOWN_CHARSET)) {
enc = StandardCharsets.UTF_8;
}
return getReader(encoding);
return getReader(enc);
}
public Reader getReader(Charset encoding) {
private Reader getReader(Charset encoding) {
return new InputStreamReader(new BufferedInputStream(new ReadContentInputStream(file)), encoding);
}
@ -94,42 +113,60 @@ public final class TextFileExtractor implements TextExtractor {
return file.getMIMEType().equals("text/plain");
}
public class TextFileExtractorException extends Exception {
public TextFileExtractorException(String msg, Throwable ex) {
super(msg, ex);
/**
* Returns the encoding of the file.
*
* @return Detected encoding or UNKNOWN_CHARSET.
*/
public Charset getEncoding() {
if (encoding != null) {
return encoding;
}
public TextFileExtractorException(String msg) {
super(msg);
}
}
public static Charset getEncoding(Content content) {
try (InputStream stream = new BufferedInputStream(new ReadContentInputStream(content))) {
// Tika first
// Encoding detection is hard. We use several libraries since the data passed in is often messy.
// First try CharsetDetector (from Tika / ICU4J).
// It is a rule-based detection approach.
try (InputStream stream = new BufferedInputStream(new ReadContentInputStream(file))) {
CharsetDetector detector = new CharsetDetector();
detector.setText(stream);
CharsetMatch tikaResult = detector.detect();
if (tikaResult != null && tikaResult.getConfidence() >= MIN_TIKA_MATCH_CONFIDENCE) {
if (tikaResult != null && tikaResult.getConfidence() >= MIN_CHARSETDETECT_MATCH_CONFIDENCE) {
try {
return Charset.forName(tikaResult.getName());
} catch (UnsupportedCharsetException ignored) {
encoding = Charset.forName(tikaResult.getName());
return encoding;
} catch (UnsupportedCharsetException ex) {
logger.log(Level.WARNING, String.format("Error converting CharsetDetector result for %s (objID=%d)", file.getName(), file.getId()), ex);
}
}
} catch (IOException ex) {
logger.log(Level.WARNING, String.format("Error setting CharsetDetector stream for %s (objID=%d)", file.getName(), file.getId()), ex);
}
// Decodetect if Tika fails or falls below confidence threshold
// If that did not work, then use DecoDetect, which is stastical
// We needed this for some Japanese text files that were incorrectly detected by CharsetDetector (with low confidence)
// This will not always work with messy data that combines some binary and some ASCII.
try {
int maxBytes = 100000;
int numBytes = Math.min(stream.available(), maxBytes);
int numBytes = maxBytes;
if (file.getSize() < maxBytes) {
numBytes = (int) file.getSize();
}
byte[] targetArray = new byte[numBytes];
stream.read(targetArray);
file.read(targetArray, 0, numBytes);
List<DecodetectResult> results = Decodetect.DECODETECT.getResults(targetArray);
if (!results.isEmpty()) {
DecodetectResult topResult = results.get(0);
if (topResult.getConfidence() >= MIN_DECODETECT_MATCH_CONFIDENCE) {
return topResult.getEncoding();
encoding = topResult.getEncoding();
return encoding;
}
}
} catch (IOException ignored) {
} catch (TskCoreException ex) {
logger.log(Level.WARNING, String.format("Error reading content from %s (objID=%d)", file.getName(), file.getId()), ex);
}
return UNKNOWN_CHARSET;
encoding = UNKNOWN_CHARSET;
return encoding;
}
}

View File

@ -135,7 +135,7 @@
<compile-dependency/>
<run-dependency>
<release-version>10</release-version>
<specification-version>10.17</specification-version>
<specification-version>10.18</specification-version>
</run-dependency>
</dependency>
<dependency>

View File

@ -127,7 +127,7 @@
<compile-dependency/>
<run-dependency>
<release-version>10</release-version>
<specification-version>10.17</specification-version>
<specification-version>10.18</specification-version>
</run-dependency>
</dependency>
<dependency>

View File

@ -2150,10 +2150,15 @@ public final class DrawableDB {
public void deleteDataSource(long dataSourceID) throws SQLException, TskCoreException {
dbWriteLock();
DrawableTransaction trans = null;
String whereClause = "WHERE data_source_obj_id = " + dataSourceID;
String tableName = "image_gallery_groups";
try {
trans = beginTransaction();
deleteDataSourceStmt.setLong(1, dataSourceID);
deleteDataSourceStmt.executeUpdate();
if (caseDb.getCaseDbAccessManager().tableExists(tableName)) {
caseDb.getCaseDbAccessManager().delete(tableName, whereClause);
}
commitTransaction(trans, true);
} catch (SQLException | TskCoreException ex) {
if (null != trans) {

View File

@ -126,11 +126,12 @@ class TextMessageAnalyzer(general.AndroidComponentAnalyzer):
artifact.addAttributes(attributes)
# Create an account
msgAccountInstance = Case.getCurrentCase().getSleuthkitCase().getCommunicationsManager().createAccountFileInstance(Account.Type.PHONE, address, general.MODULE_NAME, abstractFile);
if address is not None:
# Create an account
msgAccountInstance = Case.getCurrentCase().getSleuthkitCase().getCommunicationsManager().createAccountFileInstance(Account.Type.PHONE, address, general.MODULE_NAME, abstractFile);
# create relationship between accounts
Case.getCurrentCase().getSleuthkitCase().getCommunicationsManager().addRelationships(deviceAccountInstance, [msgAccountInstance], artifact,Relationship.Type.MESSAGE, date);
# create relationship between accounts
Case.getCurrentCase().getSleuthkitCase().getCommunicationsManager().addRelationships(deviceAccountInstance, [msgAccountInstance], artifact,Relationship.Type.MESSAGE, date);
bbartifacts.append(artifact)

View File

@ -119,7 +119,7 @@
<compile-dependency/>
<run-dependency>
<release-version>10</release-version>
<specification-version>10.17</specification-version>
<specification-version>10.18</specification-version>
</run-dependency>
</dependency>
<dependency>

View File

@ -680,7 +680,6 @@ public final class KeywordSearchIngestModule implements FileIngestModule {
* Returns true if indexing was successful and false otherwise.
*
* @param aFile Text file to analyze
* @param detectedCharset the encoding of the file
*/
private boolean indexTextFile(AbstractFile aFile) {
try {

View File

@ -1,3 +1,36 @@
---------------- VERSION 4.14.0 --------------
Specialized UIs:
- New File Discovery UI that allows you to search and filter for certain types of files.
- New Map viewer that uses either Bing (when online) or offline map tiles.
- Communications UI shows country names for phone numbers and fixed bug in summary panel.
- Fixed bugs in timeline filtering.
- Refactored backend timeline filtering code based on The Sleuth Kit datamodel changes to remove JavaFX dependency.
Data Sources:
- Added limited support for APFS disk images. Does not include encrypted volumes or ones that span multiple disks. Uses contribution to The Sleuth Kit from Blackbag Technologies.
- New data source processor that parses “XRY File Exports”.
Content Viewers:
- Added a new “Context” viewer to show where a file came from. Currently shows what message a file was attached to or what URL a file was downloaded from.
- Added support to seek and change playback speed for videos in “Application” viewer.
- Improved support for Unicode HTML files in “Application” viewer.
- Added support for webp image files in “Application” viewer.
Ingest Modules:
- Keyword Search module uses Decodetect statistical encoding detection for plain text files. Fixes issues with incorrect detection of Japanese files.
- Embedded File Extractor module uses statistical analysis to determine encoding of file names in ZIP files. Fixes issues with ZIP files created on Windows Japanese computers.
- Solr (Keyword Search module) now uses Japanese-specific tokenization using Kuromoji.
- Fixed Shellbags module in RegRipper (used by Autopsy Recent Activity module) to fix parsing errors.
- Plaso module no longer generates an error if enabled for non-disk image data sources.
- Added support for message attachments that are stored as an external file system file. Expanded Email and Android modules to use this technique.
General:
- Fixed crashes by gstreamer when a video is selected.
- Added initial capability to delete a data source from a case (excludes data in the CR).
- Changed behavior of portable case menu item to automatically open the case and warn if it was already unpacked.
- Fixed bug that caused issues when case metadata had Unicode values.
- Added new Attachment APIs to the CommunicationsArtifactHelper class to support attachments stored as external file system files.
---------------- VERSION 4.13.0 --------------
General:
- Switch from Oracle JDK to OpenJDK.

View File

@ -60,7 +60,7 @@
<compile-dependency/>
<run-dependency>
<release-version>10</release-version>
<specification-version>10.17</specification-version>
<specification-version>10.18</specification-version>
</run-dependency>
</dependency>
<dependency>

View File

@ -1,3 +1,3 @@
<project name="TSK_VERSION">
<property name="TSK_VERSION" value="4.7.0"/>
<property name="TSK_VERSION" value="4.8.0"/>
</project>

View File

@ -47,7 +47,7 @@
<compile-dependency/>
<run-dependency>
<release-version>10</release-version>
<specification-version>10.17</specification-version>
<specification-version>10.18</specification-version>
</run-dependency>
</dependency>
<dependency>

View File

@ -38,7 +38,7 @@ PROJECT_NAME = "Autopsy User Documentation"
# could be handy for archiving the generated documentation or if some version
# control system is used.
PROJECT_NUMBER = 4.13.0
PROJECT_NUMBER = 4.14.0
# Using the PROJECT_BRIEF tag one can provide an optional one line description
# for a project that appears at the top of each page and should give viewer a
@ -1025,7 +1025,7 @@ GENERATE_HTML = YES
# The default directory is: html.
# This tag requires that the tag GENERATE_HTML is set to YES.
HTML_OUTPUT = 4.13.0
HTML_OUTPUT = 4.14.0
# The HTML_FILE_EXTENSION tag can be used to specify the file extension for each
# generated HTML page (for example: .htm, .php, .asp).

View File

@ -52,14 +52,10 @@ There are no runtime ingest settings required.
Seeing Results
------
The results show up in the tree under "Results", "Extracted Content".
The results show up in the tree under "Results", "Extracted Content". The exact data extracted will vary but can include contacts, call logs, messages, and GPS entries.
\image html android_analyzer_output.PNG
Messages can also be seen by browsing to the source file in the Data Sources tree, which will display the messages in the Results Viewer to the right. Any messages with attachments will be shown under the source file in the tree, and the attachments can be seen in the Result Viewer.
\image html messages_datasource_tree.png
*/

View File

@ -9,6 +9,7 @@ Autopsy supports four types of data sources:
- Logical Files: Local files or folders. (see \ref ds_log)
- Unallocated Space Image Files: Any type of file that does not contain a file system but you want to run through ingest (see \ref ds_unalloc)
- Autopsy Logical Imager Results: The results from running the logical imager. (see \ref ds_logical_imager)
- XRY Text Export: The results from exporting text files from XRY. (see \ref ds_xry)
\section ds_add Adding a Data Source
@ -116,4 +117,15 @@ To add unallocated space image files:
This option allows you to add the results of a logical imager collection. See the \ref logical_imager_page page for details.
\section ds_xry Adding XRY Text Export Data
An XRY text export folder is expected to look similar to this:
\image html xry_folder.png
To add exported text files:
-# Choose "XRY Text Export" from the data source types.
-# Browse to the folder containing the text files.
\image html xry_dsp.png
*/

View File

@ -23,12 +23,14 @@ There are no runtime ingest settings required.
Seeing Results
------
The results of this show up in the "Results", "E-Mail Messages" portion of the tree.
The results of this show up in the "Results", "E-Mail Messages" portion of the \ref tree_viewer_page.
\image html email_results.PNG
The results can also be seen by browsing to the source file in the Data Sources tree, which will display the messages in the Results Viewer to the right. Any messages with attachments will be shown under the source file, and the attachments can be seen in the Result Viewer by selecting the message.
If an e-email has an attachment, the "Attachments" tab in the \ref content_viewer_page will be active.
\image html email_datasource_tree.png
\image html email_attachments.png
You can right click and select "View File in Directory" to navigate to the attached file. You can also switch to the "Thumbnails" tab to see a preview of any image attachments.
*/

View File

@ -0,0 +1,137 @@
/*! \page geolocation_page Geolocation
\section geo_overview Overview
The Geolocation window shows artifacts that have longitude and latitude attributes as waypoints on a map. In the field, when access to online map tile servers may not be available, the Geolocation window provides support for offline map tile data sources.
\image html geo_main.png
\section geo_usage Usage
To open the Geolocation window, go to "Tools" and then select "Geolocation".
\subsection geo_navigation General Usage
You can move the map by clicking and dragging, and zoom using either the mouse wheel or the slider in the bottom left of the map. If a map tile is not available the tile will appear grey but the waypoints will still be displayed. This is more likely to happen when changing the default \ref geo_map_options.
You can left click on a waypoint to highlight that waypoint and show a details pop-up in the upper right corner of the map. The details pop-up will be updated as you click on different waypoints. The data displayed will vary depending on the type of waypoint. For example, this is the endpoint of a GPS Route:
\image html geo_details_route.png
While this is an image with GPS coordinates found by the \ref EXIF_parser_page :
\image html geo_details.png
You can also right click on a waypoint to bring up a similar menu to what you'd see in the \ref result_viewer_page.
\image html geo_context_menu.png
\subsection geo_filter Filtering
The filters are displayed on the left side of the screen. The top filter lets you filter the waypoints based on timestamp. If enabled, you will only see waypoints with a timestamp within N days of the most recent waypoint (not the current date). When using this filter you can also choose whether you want to see waypoints with no timestamp. The second filter allows you to show waypoints only for the selected data sources.
\image html geo_filter_panel.png
If desired, the filter panel can be hidden by clicking on the vertical "Filters" tab on the top right edge of the filter panel. Clicking on that tab a second time will restore the filters panel.
\subsection geo_report Generating a Report
You can generate a KML report using the "KML Report" button in the bottom right corner of the window. The report will include only the currently visible waypoints and can be found in the "Reports" folder of your case.
\image html geo_report.png
As with other \ref reporting_page "report modules", the generated report will appear under "Reports" in the \ref tree_viewer_page. Note that you can also use the \ref report_kml report module to generate a report containing all geolocation data in the case.
\section geo_map_options Map Tile Options
<p>The Autopsy Geolocation window supports several map tile data source options. The map tile data source can be changed
on the Geolocation panel in the Options dialog. There are four options for geolocation tile data, two of which can be used offline.
<ul>
<li><b>Default online tile server</b>
<ul>
<li>The default Geolocation window tile data source is the Microsoft Virtual Earth server bing.com\maps.
</ul>
<li><b>OpenStreetMap server</b>
<ul>
<li>You can specify the address of a OSM tile server. A list of online tile servers can be found here: https://wiki.openstreetmap.org/wiki/Tile_servers.
Tile servers may have restrictions on them that prevent Autopsy from accessing their tiles. If the tiles URL is something of the form "http://tiles.example.org/${z}/${x}/${y}.png",
then you'll need to enter "http://tiles.example.org" in the options panel.
\image html geo_openstreetmap.png
</ul>
<li><b>OpenStreetMap zip file</b>
<ul>
<li>Allows offline use of zip file of OSM tile images
<li>Details on how to generate tile zip files are \ref geo_generate_zip "below".
</ul>
<li><b>MBTiles file</b>
<ul>
<li>Allows offline use of MBTiles file containing raster tiles.
<li>MBTiles raster tiles files can be downloaded from <a href="https://openmaptiles.com/downloads/planet/">OpenMapTiles</a>.
<li>OpenMapTiles provides downloads of MBTile files for areas as large as the whole planet to as small as regions of countries.
<li>For each of these regions there are at least four MBTiles available for download, please be sure to download one of the "Raster Tile" files,
not the "Vector Tiles".
</ul>
</ul>
\subsection geo_generate_zip Using Maperative to Generate Tile Image Zip Files
Maperative is a tool for drawing maps, however it can also be used to create tile images. Maperative download and documentations can be found at http://maperitive.net/ .
By default Maperative uses an online tile server to generate the map. For offline use, users can supply an OpenStreetMap raw data extract.
\subsubsection geo_generate_tile_image Generating tile image zip files using any map data source:
<ol>
<li>Download and run Maperative.
<li>Center and zoom in on area of interest. The larger the area, the more tiles that will be generated. Tiles will be generated for the area visible in the map panel.
<li>Choose whether you want to use the default zoom levels or custom ones. Zoom levels in Mapertive start at 1. As the zoom level increases so will the quantity of tiles generated as well as the detail of each tile. Generating tiles, especially for heavily populated areas, may take time, please be patient with either method.
<ul>
<li>To generate tiles using the default zoom levels, select Tools->Generate Tiles
\image html geo_gen_tiles.png
Maperative will generate tiles for zoom levels depending on the area of interest and the zoom level. For example, if you start all the way zoomed out, you will likely see levels 1 through 10 generated. If you start zoomed in, you might see levels 10 through 14.
<li>Maperative provides a command interface which allows you to generate tiles for specific zoom levels. Commands can be run in the Command prompt text field at the bottom of the Maperative window. For a full list of commands see the Maperative documentation or <a href="http://maperitive.net/docs/">http://maperitive.net/docs/</a>. The <tt>generate-tiles</tt> command can be used to generate tiles for the area visible in the map panel area. For full details on generate-tiles see the documentation included with Maperative or <a href="http://maperitive.net/docs/Commands/GenerateTiles.html">http://maperitive.net/docs/Commands/GenerateTiles.html</a>. The following is a sample command to generate tiles for zoom level 2 to 3 into the folder Tiles:
\verbatim generate-tiles minzoom=2 maxzoom=3 tilesdir=C:\Tiles \endverbatim
\image html geo_command_line.png
</ul>
<li>For use in autopsy, the generated tile images need to be in a zip file. To create a zip of tiles for use in Autopsy, zip up all of the folders in the tile file output directory. Do not include the parent directory, just the numbered folders contained within. If you use the menu bar option or did not specify a folder in your command the generated tiles will be located in &lt;Maperative Install Location&gt;\\Tiles.
\image html geo_tile_folder.png
Be sure to zip only the contents of the folder, not the top level folder.
</ol>
\subsubsection geo_add_ds Adding a data source to Maperative
Maperative can be used to generate tiles using raw data extracts from OpenStreetMaps. Data extracts (*.osm or *.osm.pbf) files can be downloaded from various locations. See https://wiki.openstreetmap.org/wiki/Planet.osm for a list of locations. Geofabrik's free download server has open OpenStreetMap data extracts for many regions. When using OSM raw data extracts in Maperative, the recommendation is to use smaller (.osm) files.
To add a data source to Maperative:
<ol>
<li>Select from the menu bar File->Open Map Source...
\image html geo_add_ds.png
<li>The new data source will appear in the bottom right corner of the window in the "Map Sources" list.
<li>To disable a Map Source, select the Map Source from the list and click the X button.
</ol>
\subsubsection geo_merge_osm Merging OSM raw data extracts
For ease of use, users may want to merge OSM raw data extracts. OSMConvert is a tool that can be used to merge OSM raw data extracts.
To merge two OSM raw data extracts country1.osm.pbf and country2.osm.pbf use the following commands. Note that this assumes that osmcovert and the files are in the same directory; if they are not be sure to use full paths.
\verbatim
osmconvert country1.osm.pbf -o=country1.o5m
osmconvert country2.osm.pbf -o=country2.o5m
osmconvert country1.o5m country2.o5m -o=together.o5m
osmconvert together.o5m -o=together.osm.pbf
\endverbatim
*/

Binary file not shown.

After

Width:  |  Height:  |  Size: 27 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 30 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 46 KiB

After

Width:  |  Height:  |  Size: 52 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 382 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 394 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 70 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 56 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 339 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 132 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 24 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 32 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 62 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 30 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 34 KiB

After

Width:  |  Height:  |  Size: 36 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 27 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 33 KiB

View File

@ -66,6 +66,7 @@ The following topics are available here:
- \subpage image_gallery_page
- \subpage timeline_page
- \subpage communications_page
- \subpage geolocation_page
- Reporting

View File

@ -38,7 +38,7 @@ PROJECT_NAME = "Autopsy"
# could be handy for archiving the generated documentation or if some version
# control system is used.
PROJECT_NUMBER = 4.13.0
PROJECT_NUMBER = 4.14.0
# Using the PROJECT_BRIEF tag one can provide an optional one line description
# for a project that appears a the top of each page and should give viewer a
@ -1066,7 +1066,7 @@ GENERATE_HTML = YES
# The default directory is: html.
# This tag requires that the tag GENERATE_HTML is set to YES.
HTML_OUTPUT = api-docs/4.13.0/
HTML_OUTPUT = api-docs/4.14.0/
# The HTML_FILE_EXTENSION tag can be used to specify the file extension for each
# generated HTML page (for example: .htm, .php, .asp).

View File

@ -4,7 +4,7 @@ app.title=Autopsy
### lowercase version of above
app.name=${branding.token}
### if left unset, version will default to today's date
app.version=4.13.0
app.version=4.14.0
### build.type must be one of: DEVELOPMENT, RELEASE
#build.type=RELEASE
build.type=DEVELOPMENT

View File

@ -161,14 +161,26 @@ sub unpack_windows_time {
# The equation can be found in several places on the Net.
# My thanks go to Dan Sully for Audio::WMA's _fileTimeToUnixTime
# which shows a perl implementation of it.
my ($low, $high) = unpack("VV", $data);
my $filetime = $high * 2 ** 32 + $low;
my $epoch_time = int(($filetime - 116444736000000000) / 10000000);
my ($lo, $hi) = unpack("VV", $data);
# my $filetime = $high * 2 ** 32 + $low;
# my $epoch_time = int(($filetime - 116444736000000000) / 10000000);
my $epoch_time;
if ($lo == 0 && $hi == 0) {
$epoch_time = 0;
} else {
$lo -= 0xd53e8000;
$hi -= 0x019db1de;
$epoch_time = int($hi*429.4967296 + $lo/1e7);
};
$epoch_time = 0 if ($epoch_time < 0);
# adjust the UNIX epoch time to the local OS's epoch time
# (see perlport's Time and Date section)
my $epoch_offset = timegm(0, 0, 0, 1, 0, 70);
$epoch_time += $epoch_offset;
# my $epoch_offset = timegm(0, 0, 0, 1, 0, 70);
# $epoch_time += $epoch_offset;
if ($epoch_time < 0 || $epoch_time > 0x7fffffff) {
$epoch_time = undef;

Binary file not shown.

Binary file not shown.

View File

@ -161,14 +161,26 @@ sub unpack_windows_time {
# The equation can be found in several places on the Net.
# My thanks go to Dan Sully for Audio::WMA's _fileTimeToUnixTime
# which shows a perl implementation of it.
my ($low, $high) = unpack("VV", $data);
my $filetime = $high * 2 ** 32 + $low;
my $epoch_time = int(($filetime - 116444736000000000) / 10000000);
my ($lo, $hi) = unpack("VV", $data);
# my $filetime = $high * 2 ** 32 + $low;
# my $epoch_time = int(($filetime - 116444736000000000) / 10000000);
my $epoch_time;
if ($lo == 0 && $hi == 0) {
$epoch_time = 0;
} else {
$lo -= 0xd53e8000;
$hi -= 0x019db1de;
$epoch_time = int($hi*429.4967296 + $lo/1e7);
};
$epoch_time = 0 if ($epoch_time < 0);
# adjust the UNIX epoch time to the local OS's epoch time
# (see perlport's Time and Date section)
my $epoch_offset = timegm(0, 0, 0, 1, 0, 70);
$epoch_time += $epoch_offset;
# my $epoch_offset = timegm(0, 0, 0, 1, 0, 70);
# $epoch_time += $epoch_offset;
if ($epoch_time < 0 || $epoch_time > 0x7fffffff) {
$epoch_time = undef;

View File

@ -47,15 +47,14 @@ sub pluginmain {
my $arch = $env->get_value("PROCESSOR_ARCHITECTURE")->get_data();
::rptMsg("<ProcessorArchitecture><mtime></mtime><artifacts><architecture mtime=\"\">" . $arch . "</architecture></artifacts></ProcessorArchitecture>");
};
::rptMsg($@) if ($@);
::logMsg($@) if ($@);
}
else {
::rptMsg($env_path." not found.");
::logMsg($env_path." not found.");
}
}
else {
::rptMsg($key_path." not found.");
::logMsg($key_path." not found.");
#::logMsg($key_path." not found.");
}
}

BIN
thirdparty/rr/rip.exe vendored

Binary file not shown.

BIN
thirdparty/rr/rr.exe vendored

Binary file not shown.

View File

@ -36,7 +36,7 @@
<compile-dependency/>
<run-dependency>
<release-version>10</release-version>
<specification-version>10.17</specification-version>
<specification-version>10.18</specification-version>
</run-dependency>
</dependency>
<dependency>

View File

@ -133,16 +133,20 @@ public final class ThunderbirdMboxFileIngestModule implements FileIngestModule {
} catch (TskException ex) {
logger.log(Level.WARNING, null, ex);
}
try {
communicationArtifactsHelper = new CommunicationArtifactsHelper(currentCase.getSleuthkitCase(),
EmailParserModuleFactory.getModuleName(), abstractFile, Account.Type.EMAIL);
} catch (TskCoreException ex) {
logger.log(Level.SEVERE, String.format("Failed to create CommunicationArtifactsHelper for file with object id = %d", abstractFile.getId()), ex);
return ProcessResult.ERROR;
boolean isPstFile = PstParser.isPstFile(abstractFile);
boolean isVcardFile = VcardParser.isVcardFile(abstractFile);
if (isMbox || isEMLFile || isPstFile || isVcardFile ) {
try {
communicationArtifactsHelper = new CommunicationArtifactsHelper(currentCase.getSleuthkitCase(),
EmailParserModuleFactory.getModuleName(), abstractFile, Account.Type.EMAIL);
} catch (TskCoreException ex) {
logger.log(Level.SEVERE, String.format("Failed to create CommunicationArtifactsHelper for file with object id = %d", abstractFile.getId()), ex);
return ProcessResult.ERROR;
}
}
if (isMbox) {
return processMBox(abstractFile);
}
@ -151,11 +155,11 @@ public final class ThunderbirdMboxFileIngestModule implements FileIngestModule {
return processEMLFile(abstractFile);
}
if (PstParser.isPstFile(abstractFile)) {
if (isPstFile) {
return processPst(abstractFile);
}
if (VcardParser.isVcardFile(abstractFile)) {
if (isVcardFile) {
return processVcard(abstractFile);
}

View File

@ -5,7 +5,7 @@
# NOTE: update_sleuthkit_version.pl updates this value and relies
# on it keeping the same name and whitespace. Don't change it.
TSK_VERSION=4.7.0
TSK_VERSION=4.8.0
# In the beginning...