mirror of
https://github.com/overcuriousity/autopsy-flatpak.git
synced 2025-07-17 02:07:42 +00:00
Merge develop into collaborative
This commit is contained in:
commit
33574bbf81
@ -1,7 +1,7 @@
|
||||
/*
|
||||
* Autopsy Forensic Browser
|
||||
*
|
||||
* Copyright 2011 Basis Technology Corp.
|
||||
* Copyright 2011-2015 Basis Technology Corp.
|
||||
* Contact: carrier <at> sleuthkit <dot> org
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
@ -62,7 +62,7 @@ class UpdateRecentCases extends JMenuItem implements DynamicMenuContent {
|
||||
menuItem.setActionCommand(caseName[i].toUpperCase());
|
||||
menuItem.addActionListener(new RecentItems(caseName[i], casePath[i]));
|
||||
comps[i] = menuItem;
|
||||
hasRecentCase = hasRecentCase || true;
|
||||
hasRecentCase = true;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -202,6 +202,13 @@
|
||||
<attr name="originalFile" stringvalue="Actions/Tools/org-sleuthkit-autopsy-filesearch-FileSearchAction.instance"/>
|
||||
<attr name="position" intvalue="200"/>
|
||||
</file>
|
||||
<folder name="RunIngestModules">
|
||||
<attr name="position" intvalue="201"/>
|
||||
<attr name="SystemFileSystem.localizingBundle" stringvalue="org.sleuthkit.autopsy.ingest.Bundle"/>
|
||||
<file name="org-sleuthkit-autopsy-ingest-RunIngestAction.shadow">
|
||||
<attr name="originalFile" stringvalue="Actions/Tools/org-sleuthkit-autopsy-ingest-RunIngestAction.instance"/>
|
||||
</file>
|
||||
</folder>
|
||||
<file name="org-sleuthkit-autopsy-report-ReportWizardAction.shadow">
|
||||
<attr name="originalFile" stringvalue="Actions/Tools/org-sleuthkit-autopsy-report-ReportWizardAction.instance"/>
|
||||
<attr name="position" intvalue="100"/>
|
||||
|
@ -1,4 +1,5 @@
|
||||
OpenIDE-Module-Name=Ingest
|
||||
Menu/Tools/RunIngestModules=Run Ingest Modules
|
||||
CTL_IngestMessageTopComponent=Messages
|
||||
HINT_IngestMessageTopComponent=Messages windows
|
||||
IngestMessageDetailsPanel.backButton.text=
|
||||
@ -105,3 +106,4 @@ IngestJobSettingsPanel.processUnallocCheckbox.toolTipText=Processes unallocated
|
||||
IngestJobSettingsPanel.processUnallocCheckbox.text=Process Unallocated Space
|
||||
IngestManager.cancellingIngest.msgDlg.text=Cancelling all currently running ingest jobs
|
||||
IngestManager.serviceIsDown.msgDlg.text={0} is down
|
||||
RunIngestSubMenu.menuItem.empty=-Empty-
|
||||
|
93
Core/src/org/sleuthkit/autopsy/ingest/RunIngestAction.java
Executable file
93
Core/src/org/sleuthkit/autopsy/ingest/RunIngestAction.java
Executable file
@ -0,0 +1,93 @@
|
||||
/*
|
||||
* Autopsy Forensic Browser
|
||||
*
|
||||
* Copyright 2011-2015 Basis Technology Corp.
|
||||
* Contact: carrier <at> sleuthkit <dot> org
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.sleuthkit.autopsy.ingest;
|
||||
|
||||
import java.awt.event.ActionEvent;
|
||||
import java.awt.event.ActionListener;
|
||||
import javax.swing.JMenuItem;
|
||||
import org.openide.awt.ActionID;
|
||||
import org.openide.awt.ActionRegistration;
|
||||
import org.openide.util.HelpCtx;
|
||||
import org.openide.util.NbBundle;
|
||||
import org.openide.util.NbBundle.Messages;
|
||||
import org.openide.util.actions.CallableSystemAction;
|
||||
import org.openide.util.actions.Presenter;
|
||||
|
||||
@ActionID(
|
||||
category = "Tools",
|
||||
id = "org.sleuthkit.autopsy.ingest.RunIngestAction"
|
||||
)
|
||||
@ActionRegistration(
|
||||
displayName = "#CTL_RunIngestAction"
|
||||
)
|
||||
@Messages("CTL_RunIngestAction=Run Ingest")
|
||||
public final class RunIngestAction extends CallableSystemAction implements Presenter.Menu, ActionListener {
|
||||
|
||||
static public RunIngestAction getInstance() {
|
||||
return new RunIngestAction();
|
||||
}
|
||||
|
||||
/**
|
||||
* Call getMenuPresenters to create images sublist
|
||||
*/
|
||||
@Override
|
||||
public void performAction() {
|
||||
getMenuPresenter();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the name of this action. This may be presented as an item in a menu.
|
||||
*
|
||||
* @return actionName
|
||||
*/
|
||||
@Override
|
||||
public String getName() {
|
||||
return NbBundle.getMessage(RunIngestAction.class, "RunIngestModulesMenu.getName.text");
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the HelpCtx associated with implementing object
|
||||
*
|
||||
* @return HelpCtx or HelpCtx.DEFAULT_HELP
|
||||
*/
|
||||
@Override
|
||||
public HelpCtx getHelpCtx() {
|
||||
return HelpCtx.DEFAULT_HELP;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a sublist of images updated by RunIngestSubMenu
|
||||
* Each has an action to perform Ingest Modules on it.
|
||||
*
|
||||
* @return the images sublist created.
|
||||
*/
|
||||
@Override
|
||||
public JMenuItem getMenuPresenter() {
|
||||
JMenuItem sublist = new RunIngestSubMenu();
|
||||
sublist.setVisible(true);
|
||||
return sublist;
|
||||
}
|
||||
|
||||
/**
|
||||
* This method does nothing, use performAction instead.
|
||||
*/
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
}
|
||||
}
|
52
Core/src/org/sleuthkit/autopsy/ingest/RunIngestModulesAction.java
Executable file
52
Core/src/org/sleuthkit/autopsy/ingest/RunIngestModulesAction.java
Executable file
@ -0,0 +1,52 @@
|
||||
/*
|
||||
* Autopsy Forensic Browser
|
||||
*
|
||||
* Copyright 2011-2015 Basis Technology Corp.
|
||||
* Contact: carrier <at> sleuthkit <dot> org
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.sleuthkit.autopsy.ingest;
|
||||
|
||||
import java.awt.event.ActionEvent;
|
||||
import java.util.Collections;
|
||||
import javax.swing.AbstractAction;
|
||||
import org.sleuthkit.datamodel.Content;
|
||||
import org.sleuthkit.datamodel.Image;
|
||||
|
||||
/**
|
||||
* This class is used to add the action to the run ingest modules menu item.
|
||||
* When the image is pressed, it should open the wizard for ingest modules.
|
||||
*/
|
||||
final class RunIngestModulesAction extends AbstractAction {
|
||||
|
||||
Image image;
|
||||
|
||||
/**
|
||||
* the constructor
|
||||
*/
|
||||
public RunIngestModulesAction(Image image) {
|
||||
this.image = image;
|
||||
}
|
||||
|
||||
/**
|
||||
* Runs the ingest modules wizard on the image.
|
||||
*
|
||||
* @param e the action event
|
||||
*/
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
final RunIngestModulesDialog ingestDialog = new RunIngestModulesDialog(Collections.<Content>singletonList(image));
|
||||
ingestDialog.display();
|
||||
}
|
||||
}
|
@ -1,7 +1,7 @@
|
||||
/*
|
||||
* Autopsy Forensic Browser
|
||||
*
|
||||
* Copyright 2013-2014 Basis Technology Corp.
|
||||
* Copyright 2013-2015 Basis Technology Corp.
|
||||
* Contact: carrier <at> sleuthkit <dot> org
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
|
99
Core/src/org/sleuthkit/autopsy/ingest/RunIngestSubMenu.java
Executable file
99
Core/src/org/sleuthkit/autopsy/ingest/RunIngestSubMenu.java
Executable file
@ -0,0 +1,99 @@
|
||||
/*
|
||||
* Autopsy Forensic Browser
|
||||
*
|
||||
* Copyright 2011-2015 Basis Technology Corp.
|
||||
* Contact: carrier <at> sleuthkit <dot> org
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.sleuthkit.autopsy.ingest;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import javax.swing.JComponent;
|
||||
import javax.swing.JMenuItem;
|
||||
import org.openide.awt.DynamicMenuContent;
|
||||
import org.openide.util.NbBundle;
|
||||
import org.sleuthkit.autopsy.casemodule.Case;
|
||||
import org.sleuthkit.datamodel.Image;
|
||||
import org.sleuthkit.datamodel.SleuthkitCase;
|
||||
import org.sleuthkit.datamodel.TskCoreException;
|
||||
|
||||
/**
|
||||
* This class is used to populate the list of open images to run ingest on them
|
||||
*/
|
||||
final class RunIngestSubMenu extends JMenuItem implements DynamicMenuContent {
|
||||
|
||||
/**
|
||||
* Creates main menu/popup menu items. It's called each time a popup menu
|
||||
* is constructed and just once for the main menu.
|
||||
* Main menu updates happen through the synchMenuPresenters() method.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
public JComponent[] getMenuPresenters() {
|
||||
List<Image> images = new ArrayList<>();
|
||||
|
||||
try {
|
||||
SleuthkitCase sk = Case.getCurrentCase().getSleuthkitCase();
|
||||
images = sk.getImages();
|
||||
} catch (IllegalStateException ex) {
|
||||
// No open Cases, create a disabled empty menu
|
||||
return getEmpty();
|
||||
} catch (TskCoreException e) {
|
||||
System.out.println("Exception getting images: " + e.getMessage());
|
||||
}
|
||||
JComponent[] comps = new JComponent[images.size()];
|
||||
|
||||
// Add Images to the component list
|
||||
for (int i = 0; i < images.size(); i++) {
|
||||
String action = images.get(i).getName();
|
||||
JMenuItem menuItem = new JMenuItem(action);
|
||||
menuItem.setActionCommand(action.toUpperCase());
|
||||
menuItem.addActionListener(new RunIngestModulesAction(images.get(i)));
|
||||
comps[i] = menuItem;
|
||||
}
|
||||
// If no images are open, create a disabled empty menu
|
||||
if (images.isEmpty()) {
|
||||
return getEmpty();
|
||||
}
|
||||
return comps;
|
||||
}
|
||||
|
||||
// returns a disabled empty menu
|
||||
private JComponent[] getEmpty() {
|
||||
JComponent[] comps = new JComponent[1];
|
||||
JMenuItem emptyMenu = new JMenuItem(NbBundle.getMessage(RunIngestSubMenu.class, "RunIngestSubMenu.menuItem.empty"));
|
||||
comps[0] = emptyMenu;
|
||||
comps[0].setEnabled(false);
|
||||
return comps;
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates main menu presenters. This method is called only by the main menu
|
||||
* processing.
|
||||
*
|
||||
* @param jcs the previously used menu items returned by previous call to
|
||||
* getMenuPresenters() or synchMenuPresenters()
|
||||
*
|
||||
* @return menu a new set of items to show in menu. Can be either an updated
|
||||
* old set of instances or a completely new one.
|
||||
*/
|
||||
@Override
|
||||
public JComponent[] synchMenuPresenters(JComponent[] jcs) {
|
||||
return getMenuPresenters();
|
||||
}
|
||||
|
||||
|
||||
}
|
@ -23,6 +23,7 @@ import java.security.NoSuchAlgorithmException;
|
||||
import java.util.logging.Level;
|
||||
import javax.xml.bind.DatatypeConverter;
|
||||
import org.openide.util.NbBundle;
|
||||
import org.python.bouncycastle.util.Arrays;
|
||||
import org.sleuthkit.autopsy.coreutils.Logger;
|
||||
import org.sleuthkit.autopsy.ingest.DataSourceIngestModule;
|
||||
import org.sleuthkit.autopsy.ingest.DataSourceIngestModuleProgress;
|
||||
@ -48,7 +49,6 @@ public class E01VerifyIngestModule implements DataSourceIngestModule {
|
||||
|
||||
private MessageDigest messageDigest;
|
||||
private boolean verified = false;
|
||||
private boolean skipped = false;
|
||||
private String calculatedHash = "";
|
||||
private String storedHash = "";
|
||||
private IngestJobContext context;
|
||||
@ -75,8 +75,10 @@ public class E01VerifyIngestModule implements DataSourceIngestModule {
|
||||
@Override
|
||||
public ProcessResult process(Content dataSource, DataSourceIngestModuleProgress statusHelper) {
|
||||
String imgName = dataSource.getName();
|
||||
|
||||
// Skip non-images
|
||||
if (!(dataSource instanceof Image)) {
|
||||
logger.log(Level.INFO, "Skipping disk image image {0}", imgName); //NON-NLS
|
||||
logger.log(Level.INFO, "Skipping non-image {0}", imgName); //NON-NLS
|
||||
services.postMessage(IngestMessage.createMessage(MessageType.INFO, E01VerifierModuleFactory.getModuleName(),
|
||||
NbBundle.getMessage(this.getClass(),
|
||||
"EwfVerifyIngestModule.process.skipNonEwf",
|
||||
@ -95,16 +97,17 @@ public class E01VerifyIngestModule implements DataSourceIngestModule {
|
||||
return ProcessResult.OK;
|
||||
}
|
||||
|
||||
if ((img.getMd5() != null) && !img.getMd5().isEmpty()) {
|
||||
storedHash = img.getMd5().toLowerCase();
|
||||
logger.log(Level.INFO, "Hash value stored in {0}: {1}", new Object[]{imgName, storedHash}); //NON-NLS
|
||||
} else {
|
||||
// Report an error for null or empty MD5
|
||||
if ((img.getMd5() == null) || img.getMd5().isEmpty()) {
|
||||
services.postMessage(IngestMessage.createMessage(MessageType.ERROR, E01VerifierModuleFactory.getModuleName(),
|
||||
NbBundle.getMessage(this.getClass(),
|
||||
"EwfVerifyIngestModule.process.noStoredHash",
|
||||
imgName)));
|
||||
return ProcessResult.ERROR;
|
||||
}
|
||||
|
||||
storedHash = img.getMd5().toLowerCase();
|
||||
logger.log(Level.INFO, "Hash value stored in {0}: {1}", new Object[]{imgName, storedHash}); //NON-NLS
|
||||
|
||||
logger.log(Level.INFO, "Starting hash verification of {0}", img.getName()); //NON-NLS
|
||||
services.postMessage(IngestMessage.createMessage(MessageType.INFO, E01VerifierModuleFactory.getModuleName(),
|
||||
@ -126,11 +129,12 @@ public class E01VerifyIngestModule implements DataSourceIngestModule {
|
||||
long chunkSize = 64 * img.getSsize();
|
||||
chunkSize = (chunkSize == 0) ? DEFAULT_CHUNK_SIZE : chunkSize;
|
||||
|
||||
int totalChunks = (int) Math.ceil(size / chunkSize);
|
||||
// Casting to double to capture decimals
|
||||
int totalChunks = (int) Math.ceil((double)size / (double)chunkSize);
|
||||
logger.log(Level.INFO, "Total chunks = {0}", totalChunks); //NON-NLS
|
||||
int read;
|
||||
|
||||
byte[] data;
|
||||
byte[] data = new byte[(int) chunkSize];
|
||||
statusHelper.switchToDeterminate(totalChunks);
|
||||
|
||||
// Read in byte size chunks and update the hash value with the data.
|
||||
@ -138,7 +142,6 @@ public class E01VerifyIngestModule implements DataSourceIngestModule {
|
||||
if (context.dataSourceIngestIsCancelled()) {
|
||||
return ProcessResult.OK;
|
||||
}
|
||||
data = new byte[(int) chunkSize];
|
||||
try {
|
||||
read = img.read(data, i * chunkSize, chunkSize);
|
||||
} catch (TskCoreException ex) {
|
||||
@ -148,7 +151,14 @@ public class E01VerifyIngestModule implements DataSourceIngestModule {
|
||||
logger.log(Level.SEVERE, msg, ex);
|
||||
return ProcessResult.ERROR;
|
||||
}
|
||||
messageDigest.update(data);
|
||||
|
||||
// Only update with the read bytes.
|
||||
if(read == chunkSize) {
|
||||
messageDigest.update(data);
|
||||
} else {
|
||||
byte[] subData = Arrays.copyOfRange(data, 0, read);
|
||||
messageDigest.update(subData);
|
||||
}
|
||||
statusHelper.progress(i);
|
||||
}
|
||||
|
||||
|
@ -87,6 +87,9 @@ public class HashDbIngestModule implements FileIngestModule {
|
||||
updateEnabledHashSets(hashDbManager.getKnownFileHashSets(), knownHashSets);
|
||||
|
||||
if (refCounter.incrementAndGet(jobId) == 1) {
|
||||
// initialize job totals
|
||||
getTotalsForIngestJobs(jobId);
|
||||
|
||||
// if first module for this job then post error msgs if needed
|
||||
|
||||
if (knownBadHashSets.isEmpty()) {
|
||||
|
@ -3,6 +3,7 @@ CTL_ReportWizardAction=Run Report
|
||||
ArtifactSelectionDialog.titleLabel.text=Select which artifacts you would like to report on:
|
||||
ArtifactSelectionDialog.okButton.text=OK
|
||||
ReportVisualPanel1.reportModulesLabel.text=Report Modules:
|
||||
ReportVisualPanel1.invalidModuleWarning=Encountered an invalid Report Module ({0})
|
||||
DefaultReportConfigurationPanel.infoLabel.text=This report will be configured on the next screen.
|
||||
ReportVisualPanel2.dataLabel.text=Select which data to report on:
|
||||
ReportVisualPanel2.deselectAllButton.text=Deselect All
|
||||
|
@ -151,7 +151,7 @@ class ReportGenerator {
|
||||
if (entry.getValue()) {
|
||||
TableReportModule module = entry.getKey();
|
||||
String reportFilePath = module.getRelativeFilePath();
|
||||
if (reportFilePath != null) {
|
||||
if (!reportFilePath.isEmpty()) {
|
||||
tableProgress.put(module, panel.addReport(module.getName(), reportPath + reportFilePath));
|
||||
} else {
|
||||
tableProgress.put(module, panel.addReport(module.getName(), null));
|
||||
@ -165,7 +165,7 @@ class ReportGenerator {
|
||||
if (entry.getValue()) {
|
||||
GeneralReportModule module = entry.getKey();
|
||||
String reportFilePath = module.getRelativeFilePath();
|
||||
if (reportFilePath != null) {
|
||||
if (!reportFilePath.isEmpty()) {
|
||||
generalProgress.put(module, panel.addReport(module.getName(), reportPath + reportFilePath));
|
||||
} else {
|
||||
generalProgress.put(module, panel.addReport(module.getName(), null));
|
||||
@ -179,7 +179,7 @@ class ReportGenerator {
|
||||
if (entry.getValue()) {
|
||||
FileReportModule module = entry.getKey();
|
||||
String reportFilePath = module.getRelativeFilePath();
|
||||
if (reportFilePath != null) {
|
||||
if (!reportFilePath.isEmpty()) {
|
||||
fileProgress.put(module, panel.addReport(module.getName(), reportPath + reportFilePath));
|
||||
} else {
|
||||
fileProgress.put(module, panel.addReport(module.getName(), null));
|
||||
|
@ -27,6 +27,7 @@ import java.util.Comparator;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.logging.Level;
|
||||
import javax.swing.JList;
|
||||
import javax.swing.JPanel;
|
||||
import javax.swing.JRadioButton;
|
||||
@ -34,11 +35,12 @@ import javax.swing.ListCellRenderer;
|
||||
import javax.swing.ListSelectionModel;
|
||||
import javax.swing.event.ListSelectionEvent;
|
||||
import javax.swing.event.ListSelectionListener;
|
||||
import org.openide.DialogDisplayer;
|
||||
import org.openide.NotifyDescriptor;
|
||||
import org.openide.util.Lookup;
|
||||
import org.openide.util.NbBundle;
|
||||
import org.sleuthkit.autopsy.coreutils.Logger;
|
||||
import org.sleuthkit.autopsy.python.JythonModuleLoader;
|
||||
import org.sleuthkit.autopsy.report.ReportHTML;
|
||||
|
||||
final class ReportVisualPanel1 extends JPanel implements ListSelectionListener {
|
||||
|
||||
@ -64,23 +66,39 @@ final class ReportVisualPanel1 extends JPanel implements ListSelectionListener {
|
||||
// Initialize the list of ReportModules
|
||||
private void initModules() {
|
||||
for (TableReportModule module : Lookup.getDefault().lookupAll(TableReportModule.class)) {
|
||||
tableModules.add(module);
|
||||
modules.add(module);
|
||||
if (moduleIsValid(module)) {
|
||||
tableModules.add(module);
|
||||
modules.add(module);
|
||||
} else {
|
||||
popupWarning(module);
|
||||
}
|
||||
}
|
||||
|
||||
for (GeneralReportModule module : Lookup.getDefault().lookupAll(GeneralReportModule.class)) {
|
||||
generalModules.add(module);
|
||||
modules.add(module);
|
||||
if (moduleIsValid(module)) {
|
||||
generalModules.add(module);
|
||||
modules.add(module);
|
||||
} else {
|
||||
popupWarning(module);
|
||||
}
|
||||
}
|
||||
|
||||
for (GeneralReportModule module : JythonModuleLoader.getGeneralReportModules()) {
|
||||
generalModules.add(module);
|
||||
modules.add(module);
|
||||
if (moduleIsValid(module)) {
|
||||
generalModules.add(module);
|
||||
modules.add(module);
|
||||
} else {
|
||||
popupWarning(module);
|
||||
}
|
||||
}
|
||||
|
||||
for (FileReportModule module : Lookup.getDefault().lookupAll(FileReportModule.class)) {
|
||||
fileModules.add(module);
|
||||
modules.add(module);
|
||||
if (moduleIsValid(module)) {
|
||||
fileModules.add(module);
|
||||
modules.add(module);
|
||||
} else {
|
||||
popupWarning(module);
|
||||
}
|
||||
}
|
||||
|
||||
Collections.sort(modules, new Comparator<ReportModule>() {
|
||||
@ -117,6 +135,20 @@ final class ReportVisualPanel1 extends JPanel implements ListSelectionListener {
|
||||
modulesJList.setSelectedIndex(selectedIndex);
|
||||
}
|
||||
|
||||
// Make sure that the report module has a valid non-null name.
|
||||
private boolean moduleIsValid(ReportModule module) {
|
||||
return module.getName() != null && !module.getName().isEmpty()
|
||||
&& module.getRelativeFilePath() != null;
|
||||
}
|
||||
|
||||
private void popupWarning(ReportModule module) {
|
||||
String moduleClassName = module.getClass().getSimpleName();
|
||||
logger.log(Level.WARNING, "Invalid ReportModule: {0}", moduleClassName); // NON_NLS
|
||||
DialogDisplayer.getDefault().notify(new NotifyDescriptor.Message(
|
||||
NbBundle.getMessage(ReportVisualPanel1.class, "ReportVisualPanel1.invalidModuleWarning", moduleClassName),
|
||||
NotifyDescriptor.ERROR_MESSAGE));
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return NbBundle.getMessage(this.getClass(), "ReportVisualPanel1.getName.text");
|
||||
|
@ -1,7 +1,7 @@
|
||||
/*
|
||||
* Autopsy Forensic Browser
|
||||
*
|
||||
* Copyright 2013 Basis Technology Corp.
|
||||
* Copyright 2013-15 Basis Technology Corp.
|
||||
* Contact: carrier <at> sleuthkit <dot> org
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
@ -21,10 +21,12 @@ package org.sleuthkit.autopsy.timeline;
|
||||
import java.io.IOException;
|
||||
import java.net.MalformedURLException;
|
||||
import java.net.URL;
|
||||
import java.util.logging.Level;
|
||||
import javafx.fxml.FXMLLoader;
|
||||
import javafx.scene.Node;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.openide.util.Exceptions;
|
||||
import org.sleuthkit.autopsy.coreutils.Logger;
|
||||
import org.sleuthkit.autopsy.coreutils.ThreadConfined;
|
||||
|
||||
/**
|
||||
* This class supports programmer productivity by abstracting frequently used
|
||||
@ -34,32 +36,53 @@ import org.openide.util.Exceptions;
|
||||
* at
|
||||
* http://stackoverflow.com/questions/11734885/javafx2-very-poor-performance-when-adding-custom-made-fxmlpanels-to-gridpane.
|
||||
*
|
||||
* NOTE: As described in the link above above, using FXMLConstructor will be
|
||||
* inefficient if FXML is used as a template for many similar items. In that use
|
||||
* case, it is much faster to build the entire hierarchy in Java. This class is
|
||||
* intended only to remove the boilerplate initialization code when defining a
|
||||
* relatively static layout
|
||||
*
|
||||
* TODO: find a way to move this to CoreUtils and remove duplicate verison in
|
||||
* image analyzer
|
||||
*/
|
||||
public class FXMLConstructor {
|
||||
|
||||
static public void construct(Node n, String fxmlFileName) {
|
||||
final String name = "nbres:/" + StringUtils.replace(n.getClass().getPackage().getName(), ".", "/") + "/" + fxmlFileName; // NON-NLS
|
||||
System.out.println(name);
|
||||
private static final Logger LOGGER = Logger.getLogger(FXMLConstructor.class.getName());
|
||||
|
||||
/**
|
||||
* Load an fxml file and initialize a node with it. Since this manipulates
|
||||
* the node, it must be called on the JFX thread.
|
||||
*
|
||||
*
|
||||
* @param node a node to initialize from a loaded FXML
|
||||
* @param fxmlFileName the the file name of the FXML to load, relative to
|
||||
* the package that the class of node is defined in.
|
||||
*/
|
||||
@ThreadConfined(type = ThreadConfined.ThreadType.JFX)
|
||||
static public void construct(Node node, String fxmlFileName) {
|
||||
final String name = "nbres:/" + StringUtils.replace(node.getClass().getPackage().getName(), ".", "/") + "/" + fxmlFileName; // NON-NLS
|
||||
|
||||
try {
|
||||
FXMLLoader fxmlLoader = new FXMLLoader(new URL(name));
|
||||
fxmlLoader.setRoot(n);
|
||||
fxmlLoader.setController(n);
|
||||
fxmlLoader.setRoot(node);
|
||||
fxmlLoader.setController(node);
|
||||
|
||||
try {
|
||||
fxmlLoader.load();
|
||||
} catch (IOException exception) {
|
||||
LOGGER.log(Level.SEVERE, "FXMLConstructor was unable to load FXML, falling back on default Class Loader, and trying again.", exception);
|
||||
try {
|
||||
fxmlLoader.setClassLoader(FXMLLoader.getDefaultClassLoader());
|
||||
fxmlLoader.load();
|
||||
} catch (IOException ex) {
|
||||
Exceptions.printStackTrace(ex);
|
||||
LOGGER.log(Level.SEVERE, "FXMLConstructor was unable to load FXML, node initialization may not be complete.", ex);
|
||||
}
|
||||
}
|
||||
} catch (MalformedURLException ex) {
|
||||
Exceptions.printStackTrace(ex);
|
||||
LOGGER.log(Level.SEVERE, "FXMLConstructor was unable to load FXML, node initialization may not be complete.", ex);
|
||||
}
|
||||
}
|
||||
|
||||
private FXMLConstructor() {
|
||||
}
|
||||
}
|
||||
|
@ -23,10 +23,11 @@ import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.function.BiFunction;
|
||||
import java.util.logging.Level;
|
||||
import javafx.scene.image.Image;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.openide.util.Exceptions;
|
||||
import org.openide.util.NbBundle;
|
||||
import org.sleuthkit.autopsy.coreutils.Logger;
|
||||
import org.sleuthkit.autopsy.timeline.zooming.EventTypeZoomLevel;
|
||||
import org.sleuthkit.datamodel.AbstractFile;
|
||||
import org.sleuthkit.datamodel.BlackboardArtifact;
|
||||
@ -57,7 +58,7 @@ public enum MiscTypes implements EventType, ArtifactEventType {
|
||||
BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DATETIME,
|
||||
new AttributeExtractor(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_PROG_NAME),
|
||||
new AttributeExtractor(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_LOCATION),
|
||||
(BlackboardArtifact artf, Map<BlackboardAttribute.ATTRIBUTE_TYPE, BlackboardAttribute> attrMap) -> {
|
||||
(artf, attrMap) -> {
|
||||
final BlackboardAttribute latStart = attrMap.get(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_GEO_LATITUDE_START);
|
||||
final BlackboardAttribute longStart = attrMap.get(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_GEO_LONGITUDE_START);
|
||||
final BlackboardAttribute latEnd = attrMap.get(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_GEO_LATITUDE_END);
|
||||
@ -129,18 +130,16 @@ public enum MiscTypes implements EventType, ArtifactEventType {
|
||||
BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DATETIME_CREATED,
|
||||
new AttributeExtractor(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DEVICE_MAKE),
|
||||
new AttributeExtractor(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DEVICE_MODEL),
|
||||
(BlackboardArtifact t,
|
||||
Map<BlackboardAttribute.ATTRIBUTE_TYPE, BlackboardAttribute> u) -> {
|
||||
(artifact, attributeMap) -> {
|
||||
try {
|
||||
AbstractFile f = t.getSleuthkitCase().getAbstractFileById(t.getObjectID());
|
||||
if (f != null) {
|
||||
return f.getName();
|
||||
AbstractFile file = artifact.getSleuthkitCase().getAbstractFileById(artifact.getObjectID());
|
||||
if (file != null) {
|
||||
return file.getName();
|
||||
}
|
||||
return " error loading file name"; // NON-NLS
|
||||
} catch (TskCoreException ex) {
|
||||
Exceptions.printStackTrace(ex);
|
||||
return " error loading file name"; // NON-NLS
|
||||
Logger.getLogger(MiscTypes.class.getName()).log(Level.SEVERE, "Exif event type failed to look up backing file name", ex);
|
||||
}
|
||||
return " error loading file name"; // NON-NLS
|
||||
}),
|
||||
DEVICES_ATTACHED(NbBundle.getMessage(MiscTypes.class, "MiscTypes.devicesAttached.name"), "usb_devices.png", // NON-NLS
|
||||
BlackboardArtifact.ARTIFACT_TYPE.TSK_DEVICE_ATTACHED,
|
||||
@ -185,26 +184,41 @@ public enum MiscTypes implements EventType, ArtifactEventType {
|
||||
|
||||
private final BiFunction<BlackboardArtifact, Map<BlackboardAttribute.ATTRIBUTE_TYPE, BlackboardAttribute>, String> shortExtractor;
|
||||
|
||||
/**
|
||||
* {@inheritDoc }
|
||||
*/
|
||||
@Override
|
||||
public BiFunction<BlackboardArtifact, Map<BlackboardAttribute.ATTRIBUTE_TYPE, BlackboardAttribute>, String> getFullExtractor() {
|
||||
return longExtractor;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc }
|
||||
*/
|
||||
@Override
|
||||
public BiFunction<BlackboardArtifact, Map<BlackboardAttribute.ATTRIBUTE_TYPE, BlackboardAttribute>, String> getMedExtractor() {
|
||||
return medExtractor;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc }
|
||||
*/
|
||||
@Override
|
||||
public BiFunction<BlackboardArtifact, Map<BlackboardAttribute.ATTRIBUTE_TYPE, BlackboardAttribute>, String> getShortExtractor() {
|
||||
return shortExtractor;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc }
|
||||
*/
|
||||
@Override
|
||||
public BlackboardAttribute.ATTRIBUTE_TYPE getDateTimeAttrubuteType() {
|
||||
return dateTimeAttributeType;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc }
|
||||
*/
|
||||
@Override
|
||||
public EventTypeZoomLevel getZoomLevel() {
|
||||
return EventTypeZoomLevel.SUB_TYPE;
|
||||
|
@ -1071,9 +1071,12 @@ public class EventDB {
|
||||
String timeZone = TimeLineController.getTimeZone().get().equals(TimeZone.getDefault()) ? ", 'localtime'" : ""; // NON-NLS
|
||||
String typeColumn = typeColumnHelper(useSubTypes);
|
||||
|
||||
//compose query string
|
||||
//compose query string, new-lines only for nicer formatting if printing the entire query
|
||||
String query = "SELECT strftime('" + strfTimeFormat + "',time , 'unixepoch'" + timeZone + ") AS interval," // NON-NLS
|
||||
+ " group_concat(events.event_id) as event_ids, min(time), max(time), " + typeColumn + ", " + descriptionColumn // NON-NLS
|
||||
+ "\n group_concat(events.event_id) as event_ids,"
|
||||
+ "\n group_concat(CASE WHEN hash_hit = 1 THEN event_id ELSE NULL END) as hash_hits,"
|
||||
+ "\n group_concat(CASE WHEN tagged = 1 THEN event_id ELSE NULL END) as taggeds,"
|
||||
+ "\n min(time), max(time), " + typeColumn + ", " + descriptionColumn // NON-NLS
|
||||
+ "\n FROM events" + useHashHitTablesHelper(filter) + useTagTablesHelper(filter) // NON-NLS
|
||||
+ "\n WHERE time >= " + start + " AND time < " + end + " AND " + SQLHelper.getSQLWhere(filter) // NON-NLS
|
||||
+ "\n GROUP BY interval, " + typeColumn + " , " + descriptionColumn // NON-NLS
|
||||
@ -1081,6 +1084,7 @@ public class EventDB {
|
||||
|
||||
// perform query and map results to AggregateEvent objects
|
||||
List<AggregateEvent> events = new ArrayList<>();
|
||||
|
||||
DBLock.lock();
|
||||
|
||||
try (Statement createStatement = con.createStatement();
|
||||
@ -1117,23 +1121,8 @@ public class EventDB {
|
||||
String description = rs.getString(SQLHelper.getDescriptionColumn(descriptionLOD));
|
||||
EventType type = useSubTypes ? RootEventType.allTypes.get(rs.getInt("sub_type")) : BaseTypes.values()[rs.getInt("base_type")];// NON-NLS
|
||||
|
||||
Set<Long> hashHits = new HashSet<>();
|
||||
String hashHitQuery = "SELECT group_concat(event_id) FROM events WHERE event_id IN (" + eventIDsString + ") AND hash_hit = 1";// NON-NLS
|
||||
try (Statement stmt = con.createStatement();
|
||||
ResultSet hashHitsRS = stmt.executeQuery(hashHitQuery)) {
|
||||
while (hashHitsRS.next()) {
|
||||
hashHits = SQLHelper.unGroupConcat(hashHitsRS.getString("group_concat(event_id)"), Long::valueOf);// NON-NLS
|
||||
}
|
||||
}
|
||||
|
||||
Set<Long> tagged = new HashSet<>();
|
||||
String taggedQuery = "SELECT group_concat(event_id) FROM events WHERE event_id IN (" + eventIDsString + ") AND tagged = 1";// NON-NLS
|
||||
try (Statement stmt = con.createStatement();
|
||||
ResultSet taggedRS = stmt.executeQuery(taggedQuery)) {
|
||||
while (taggedRS.next()) {
|
||||
tagged = SQLHelper.unGroupConcat(taggedRS.getString("group_concat(event_id)"), Long::valueOf);// NON-NLS
|
||||
}
|
||||
}
|
||||
Set<Long> hashHits = SQLHelper.unGroupConcat(rs.getString("hash_hits"), Long::valueOf);
|
||||
Set<Long> tagged = SQLHelper.unGroupConcat(rs.getString("taggeds"), Long::valueOf);
|
||||
|
||||
return new AggregateEvent(interval, type, eventIDs, hashHits, tagged,
|
||||
description, descriptionLOD);
|
||||
|
@ -22,6 +22,7 @@ import java.lang.reflect.InvocationTargetException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.logging.Level;
|
||||
import javafx.beans.Observable;
|
||||
import javax.swing.Action;
|
||||
import org.joda.time.DateTime;
|
||||
@ -29,8 +30,8 @@ import org.joda.time.DateTimeZone;
|
||||
import org.openide.nodes.Children;
|
||||
import org.openide.nodes.PropertySupport;
|
||||
import org.openide.nodes.Sheet;
|
||||
import org.openide.util.Exceptions;
|
||||
import org.openide.util.lookup.Lookups;
|
||||
import org.sleuthkit.autopsy.coreutils.Logger;
|
||||
import org.sleuthkit.autopsy.datamodel.DataModelActionsFactory;
|
||||
import org.sleuthkit.autopsy.datamodel.DisplayableItemNode;
|
||||
import org.sleuthkit.autopsy.datamodel.DisplayableItemNodeVisitor;
|
||||
@ -46,6 +47,8 @@ import org.sleuthkit.datamodel.Content;
|
||||
*/
|
||||
class EventNode extends DisplayableItemNode {
|
||||
|
||||
private static final Logger LOGGER = Logger.getLogger(EventNode.class.getName());
|
||||
|
||||
private final TimeLineEvent e;
|
||||
|
||||
EventNode(TimeLineEvent eventById, AbstractFile file, BlackboardArtifact artifact) {
|
||||
@ -75,7 +78,7 @@ class EventNode extends DisplayableItemNode {
|
||||
try {
|
||||
timePropery.setValue(getDateTimeString());
|
||||
} catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException ex) {
|
||||
Exceptions.printStackTrace(ex);
|
||||
LOGGER.log(Level.SEVERE, "unexpected error setting date/time property on EventNode explorer node", ex);
|
||||
}
|
||||
});
|
||||
|
||||
@ -105,7 +108,7 @@ class EventNode extends DisplayableItemNode {
|
||||
final List<Action> factoryActions = DataModelActionsFactory.getActions(content, artifact != null);
|
||||
|
||||
actionsList.addAll(factoryActions);
|
||||
return actionsList.toArray(new Action[0]);
|
||||
return actionsList.toArray(new Action[actionsList.size()]);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -118,7 +121,11 @@ class EventNode extends DisplayableItemNode {
|
||||
throw new UnsupportedOperationException("Not supported yet."); // NON-NLS //To change body of generated methods, choose Tools | Templates.
|
||||
}
|
||||
|
||||
class TimeProperty extends PropertySupport.ReadWrite<String> {
|
||||
/**
|
||||
* We use TimeProperty instead of a normal NodeProperty to correctly display
|
||||
* the date/time when the user changes the timezone setting.
|
||||
*/
|
||||
private class TimeProperty extends PropertySupport.ReadWrite<String> {
|
||||
|
||||
private String value;
|
||||
|
||||
@ -127,7 +134,7 @@ class EventNode extends DisplayableItemNode {
|
||||
return false;
|
||||
}
|
||||
|
||||
public TimeProperty(String name, String displayName, String shortDescription, String value) {
|
||||
TimeProperty(String name, String displayName, String shortDescription, String value) {
|
||||
super(name, String.class, displayName, shortDescription);
|
||||
setValue("suppressCustomEditor", Boolean.TRUE); // remove the "..." (editing) button NON-NLS
|
||||
this.value = value;
|
||||
|
Loading…
x
Reference in New Issue
Block a user