mirror of
https://github.com/overcuriousity/autopsy-flatpak.git
synced 2025-07-17 18:17:43 +00:00
Merge remote-tracking branch 'upstream/master'
This commit is contained in:
commit
1277f840f8
@ -280,6 +280,8 @@ public class FileManager implements Closeable {
|
||||
//added.add(localFileAdded);
|
||||
//send new content event
|
||||
//for now reusing ingest events, in future this will be replaced by datamodel / observer sending out events
|
||||
// @@@ Is this the right place for this? A directory tree refresh will be triggered, so this may be creating a race condition
|
||||
// since the transaction is not yet committed.
|
||||
IngestServices.getDefault().fireModuleContentEvent(new ModuleContentEvent(localFileAdded));
|
||||
}
|
||||
}
|
||||
|
@ -310,6 +310,11 @@
|
||||
<attr name="instanceCreate" methodvalue="org.sleuthkit.autopsy.report.ReportBodyFile.getDefault"/>
|
||||
<attr name="position" intvalue="902"/>
|
||||
</file>
|
||||
<file name="org-sleuthkit-autopsy-report-FileReportText.instance">
|
||||
<attr name="instanceOf" stringvalue="org.sleuthkit.autopsy.report.FileReportModule"/>
|
||||
<attr name="instanceCreate" methodvalue="org.sleuthkit.autopsy.report.FileReportText.getDefault"/>
|
||||
<attr name="position" intvalue="903"/>
|
||||
</file>
|
||||
<!--<folder name="JavaHelp">
|
||||
<file name="casemodule-helpset.xml" url="casemodule-helpset.xml">
|
||||
<attr name="position" intvalue="3075"/>
|
||||
@ -368,7 +373,7 @@
|
||||
<attr name="originalFile" stringvalue="Actions/Tools/org-sleuthkit-autopsy-ingest-IngestMessagesAction.instance"/>
|
||||
</file>
|
||||
</folder>
|
||||
<folder name="QuickSearch_hidden" />
|
||||
<folder name="QuickSearch_hidden"/>
|
||||
</folder>
|
||||
|
||||
|
||||
|
@ -358,6 +358,7 @@ public class DataResultPanel extends javax.swing.JPanel implements DataResult, C
|
||||
|
||||
this.rootNode = selectedNode;
|
||||
if (this.rootNode != null) {
|
||||
dummyNodeListener.reset();
|
||||
this.rootNode.addNodeListener(dummyNodeListener);
|
||||
}
|
||||
|
||||
@ -612,23 +613,32 @@ public class DataResultPanel extends javax.swing.JPanel implements DataResult, C
|
||||
|
||||
private class DummyNodeListener implements NodeListener {
|
||||
private static final String DUMMY_NODE_DISPLAY_NAME = "Please Wait...";
|
||||
private boolean reload = false;
|
||||
private volatile boolean load = true;
|
||||
|
||||
public void reset() {
|
||||
load = true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void childrenAdded(final NodeMemberEvent nme) {
|
||||
if (reload) {
|
||||
public void childrenAdded(NodeMemberEvent nme) {
|
||||
Node[] delta = nme.getDelta();
|
||||
if (load && containsReal(delta)) {
|
||||
load = false;
|
||||
setupTabs(nme.getNode());
|
||||
reload = false;
|
||||
}
|
||||
}
|
||||
|
||||
private boolean containsReal(Node[] delta) {
|
||||
for (Node n : delta) {
|
||||
if (!n.getDisplayName().equals(DUMMY_NODE_DISPLAY_NAME)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void childrenRemoved(NodeMemberEvent nme) {
|
||||
Node removed = nme.getNode();
|
||||
if (removed.getDisplayName().equals(DUMMY_NODE_DISPLAY_NAME)) {
|
||||
// set up tabs if the node removed is a waiting node
|
||||
reload = false;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -243,8 +243,7 @@ public class DataResultViewerTable extends AbstractDataResultViewer {
|
||||
this.setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
|
||||
try {
|
||||
boolean hasChildren = false;
|
||||
|
||||
|
||||
|
||||
if (selectedNode != null) {
|
||||
hasChildren = selectedNode.getChildren().getNodesCount() > 0;
|
||||
}
|
||||
@ -257,6 +256,7 @@ public class DataResultViewerTable extends AbstractDataResultViewer {
|
||||
// if there's no selection node, do nothing
|
||||
if (hasChildren) {
|
||||
Node root = selectedNode;
|
||||
dummyNodeListener.reset();
|
||||
root.addNodeListener(dummyNodeListener);
|
||||
setupTable(root);
|
||||
} else {
|
||||
@ -478,21 +478,32 @@ public class DataResultViewerTable extends AbstractDataResultViewer {
|
||||
|
||||
private class DummyNodeListener implements NodeListener {
|
||||
private static final String DUMMY_NODE_DISPLAY_NAME = "Please Wait...";
|
||||
private boolean reload = false;
|
||||
private volatile boolean load = true;
|
||||
|
||||
public void reset() {
|
||||
load = true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void childrenAdded(NodeMemberEvent nme) {
|
||||
if (reload) {
|
||||
Node[] delta = nme.getDelta();
|
||||
if (load && containsReal(delta)) {
|
||||
load = false;
|
||||
setupTable(nme.getNode());
|
||||
reload = false;
|
||||
}
|
||||
}
|
||||
|
||||
private boolean containsReal(Node[] delta) {
|
||||
for (Node n : delta) {
|
||||
if (!n.getDisplayName().equals(DUMMY_NODE_DISPLAY_NAME)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void childrenRemoved(NodeMemberEvent nme) {
|
||||
Node removed = nme.getNode();
|
||||
if (removed.getDisplayName().equals(DUMMY_NODE_DISPLAY_NAME)) {
|
||||
reload = true;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -528,9 +528,26 @@ public final class DirectoryTreeTopComponent extends TopComponent implements Dat
|
||||
}
|
||||
} // changed current case
|
||||
else if (changed.equals(Case.CASE_CURRENT_CASE)) {
|
||||
|
||||
// case opened
|
||||
if (newValue != null) {
|
||||
// When a case is closed, the old value of this property is the
|
||||
// closed Case object and the new value is null. When a case is
|
||||
// opened, the old value is null and the new value is the new Case
|
||||
// object.
|
||||
// @@@ This needs to be revisited. Perhaps case closed and case
|
||||
// opened events instead of property change events would be a better
|
||||
// solution. Either way, more probably needs to be done to clean up
|
||||
// data model objects when a case is closed.
|
||||
if (oldValue != null && newValue == null) {
|
||||
// The current case has been closed. Reset the ExplorerManager.
|
||||
Node emptyNode = new AbstractNode(Children.LEAF);
|
||||
em.setRootContext(emptyNode);
|
||||
}
|
||||
else if (newValue != null) {
|
||||
// A new case has been opened. Reset the forward and back
|
||||
// buttons. Note that a call to CoreComponentControl.openCoreWindows()
|
||||
// by the new Case object will lead to a componentOpened() call
|
||||
// that will repopulate the tree.
|
||||
// @@@ The repopulation of the tree in this fashion also merits
|
||||
// reconsideration.
|
||||
resetHistory();
|
||||
}
|
||||
} // if the image is added to the case
|
||||
|
@ -30,3 +30,13 @@ ReportProgressPanel.processingLabel.text=processingLabel
|
||||
ReportGenerationPanel.titleLabel.text=Report Generation Progress
|
||||
ReportVisualPanel2.taggedResultsRadioButton.text=Tagged Results
|
||||
ReportVisualPanel2.allResultsRadioButton.text=All Results
|
||||
FileReportConfigurationPanel.jLabel1.text=Select Items to Report:
|
||||
FileReportConfigurationPanel.selectAllButton.text=Select All
|
||||
FileReportConfigurationPanel.deselectAllButton.text=Deselect All
|
||||
FileReportConfigurationDialog.selectAllButton.text=Select All
|
||||
FileReportConfigurationDialog.deselectAllButton.text=Deselect All
|
||||
FileReportConfigurationDialog.jLabel1.text=Select items to include in the File Report
|
||||
FileReportConfigurationDialog.okButton.text=OK
|
||||
ReportWizardFileOptionsVisualPanel.selectAllButton.text=Select All
|
||||
ReportWizardFileOptionsVisualPanel.deselectAllButton.text=Deselect All
|
||||
ReportWizardFileOptionsVisualPanel.jLabel1.text=Select items to include in File Report:
|
||||
|
138
Core/src/org/sleuthkit/autopsy/report/FileReportDataTypes.java
Executable file
138
Core/src/org/sleuthkit/autopsy/report/FileReportDataTypes.java
Executable file
@ -0,0 +1,138 @@
|
||||
/*
|
||||
* Autopsy Forensic Browser
|
||||
*
|
||||
* Copyright 2013 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.report;
|
||||
|
||||
import org.sleuthkit.datamodel.AbstractFile;
|
||||
import org.sleuthkit.datamodel.TskCoreException;
|
||||
import org.sleuthkit.datamodel.TskData;
|
||||
|
||||
/**
|
||||
* Represents Column Headers for FileList Reports.
|
||||
*
|
||||
* Encapsulates functionality for getting column values from Files.
|
||||
*
|
||||
* @author jwallace
|
||||
*/
|
||||
public enum FileReportDataTypes {
|
||||
|
||||
NAME("Name") {
|
||||
@Override
|
||||
public String getValue(AbstractFile file) {
|
||||
return file.getName();
|
||||
}
|
||||
},
|
||||
FILE_EXT("File Extension") {
|
||||
@Override
|
||||
public String getValue(AbstractFile file) {
|
||||
String name = file.getName();
|
||||
int extIndex = name.lastIndexOf(".");
|
||||
return (extIndex == -1 ? "" : name.substring(extIndex));
|
||||
}
|
||||
},
|
||||
FILE_TYPE("File Type") {
|
||||
@Override
|
||||
public String getValue(AbstractFile file) {
|
||||
return file.getMetaTypeAsString();
|
||||
}
|
||||
},
|
||||
DELETED("Is Deleted") {
|
||||
@Override
|
||||
public String getValue(AbstractFile file) {
|
||||
if (file.getMetaFlagsAsString().equals(TskData.TSK_FS_META_FLAG_ENUM.UNALLOC.toString())) {
|
||||
return "yes";
|
||||
}
|
||||
return "";
|
||||
}
|
||||
},
|
||||
A_TIME("Last Accessed") {
|
||||
@Override
|
||||
public String getValue(AbstractFile file) {
|
||||
return file.getAtimeAsDate();
|
||||
}
|
||||
},
|
||||
CR_TIME("File Created") {
|
||||
@Override
|
||||
public String getValue(AbstractFile file) {
|
||||
return file.getCrtimeAsDate();
|
||||
}
|
||||
},
|
||||
M_TIME("Last Modified") {
|
||||
@Override
|
||||
public String getValue(AbstractFile file) {
|
||||
return file.getMtimeAsDate();
|
||||
}
|
||||
},
|
||||
SIZE("Size") {
|
||||
@Override
|
||||
public String getValue(AbstractFile file) {
|
||||
return String.valueOf(file.getSize());
|
||||
}
|
||||
},
|
||||
ADDRESS("Address") {
|
||||
@Override
|
||||
public String getValue(AbstractFile file) {
|
||||
return String.valueOf(file.getMetaAddr());
|
||||
}
|
||||
},
|
||||
HASH_VALUE("Hash Value") {
|
||||
@Override
|
||||
public String getValue(AbstractFile file) {
|
||||
return file.getMd5Hash();
|
||||
}
|
||||
},
|
||||
KNOWN_STATUS("Known Status") {
|
||||
@Override
|
||||
public String getValue(AbstractFile file) {
|
||||
return file.getKnown().getName();
|
||||
}
|
||||
},
|
||||
PERMISSIONS("Permissions") {
|
||||
@Override
|
||||
public String getValue(AbstractFile file) {
|
||||
return file.getModesAsString();
|
||||
}
|
||||
},
|
||||
FULL_PATH("Full Path") {
|
||||
@Override
|
||||
public String getValue(AbstractFile file) {
|
||||
try {
|
||||
return file.getUniquePath();
|
||||
} catch (TskCoreException ex) {
|
||||
return "";
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
private String name;
|
||||
|
||||
FileReportDataTypes(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return this.name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the value of the column from the file.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public abstract String getValue(AbstractFile file);
|
||||
}
|
60
Core/src/org/sleuthkit/autopsy/report/FileReportModule.java
Executable file
60
Core/src/org/sleuthkit/autopsy/report/FileReportModule.java
Executable file
@ -0,0 +1,60 @@
|
||||
/*
|
||||
* Autopsy Forensic Browser
|
||||
*
|
||||
* Copyright 2013 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.report;
|
||||
|
||||
import java.util.List;
|
||||
import org.sleuthkit.datamodel.AbstractFile;
|
||||
|
||||
/**
|
||||
* A Report Module that reports information on files in a case.
|
||||
*
|
||||
* @author jwallace
|
||||
*/
|
||||
public interface FileReportModule extends ReportModule {
|
||||
/**
|
||||
* Initialize the report which will be stored at the given path.
|
||||
* @param path
|
||||
*/
|
||||
public void startReport(String path);
|
||||
|
||||
/**
|
||||
* End the report.
|
||||
* Will be called after the entire report has been written.
|
||||
*/
|
||||
public void endReport();
|
||||
|
||||
/**
|
||||
* Start the file list table.
|
||||
* @param headers The columns that should be included in the table.
|
||||
*/
|
||||
public void startTable(List<FileReportDataTypes> headers);
|
||||
|
||||
/**
|
||||
* Add the given AbstractFile as a row in the table.
|
||||
* Guaranteed to be called between startTable and endTable.
|
||||
* @param toAdd the AbstractFile to be added.
|
||||
* @param columns the columns that should be included
|
||||
*/
|
||||
public void addRow(AbstractFile toAdd, List<FileReportDataTypes> columns);
|
||||
|
||||
/**
|
||||
* Close the table.
|
||||
*/
|
||||
public void endTable();
|
||||
}
|
138
Core/src/org/sleuthkit/autopsy/report/FileReportText.java
Executable file
138
Core/src/org/sleuthkit/autopsy/report/FileReportText.java
Executable file
@ -0,0 +1,138 @@
|
||||
/*
|
||||
* Autopsy Forensic Browser
|
||||
*
|
||||
* Copyright 2013 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.report;
|
||||
|
||||
import java.io.BufferedWriter;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStreamWriter;
|
||||
import java.io.Writer;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
import org.sleuthkit.datamodel.AbstractFile;
|
||||
|
||||
/**
|
||||
* A Tab-delimited text report of the files in the case.
|
||||
*
|
||||
* @author jwallace
|
||||
*/
|
||||
public class FileReportText implements FileReportModule {
|
||||
private static final Logger logger = Logger.getLogger(FileReportText.class.getName());
|
||||
private String reportPath;
|
||||
private Writer out;
|
||||
private static final String FILE_NAME = "file-report.txt";
|
||||
|
||||
private static FileReportText instance;
|
||||
|
||||
// Get the default implementation of this report
|
||||
public static synchronized FileReportText getDefault() {
|
||||
if (instance == null) {
|
||||
instance = new FileReportText();
|
||||
}
|
||||
return instance;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void startReport(String path) {
|
||||
this.reportPath = path + FILE_NAME;
|
||||
try {
|
||||
out = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(this.reportPath)));
|
||||
} catch (IOException ex) {
|
||||
logger.log(Level.WARNING, "Failed to create report text file", ex);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void endReport() {
|
||||
if (out != null) {
|
||||
try {
|
||||
out.close();
|
||||
} catch (IOException ex) {
|
||||
logger.log(Level.WARNING, "Could not close output writer when ending report.", ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private String getTabDelimitedList(List<String> list) {
|
||||
StringBuilder output = new StringBuilder();
|
||||
Iterator<String> it = list.iterator();
|
||||
while(it.hasNext()) {
|
||||
output.append(it.next()).append((it.hasNext() ? "\t" : System.lineSeparator()));
|
||||
}
|
||||
return output.toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void startTable(List<FileReportDataTypes> headers) {
|
||||
List<String> titles = new ArrayList<>();
|
||||
for(FileReportDataTypes col : headers) {
|
||||
titles.add(col.getName());
|
||||
}
|
||||
try {
|
||||
out.write(getTabDelimitedList(titles));
|
||||
} catch (IOException ex) {
|
||||
logger.log(Level.WARNING, "Error when writing headers to report file: {0}", ex);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addRow(AbstractFile toAdd, List<FileReportDataTypes> columns) {
|
||||
List<String> cells = new ArrayList<>();
|
||||
for(FileReportDataTypes type : columns) {
|
||||
cells.add(type.getValue(toAdd));
|
||||
}
|
||||
try {
|
||||
out.write(getTabDelimitedList(cells));
|
||||
} catch (IOException ex) {
|
||||
logger.log(Level.WARNING, "Error when writing row to report file: {0}", ex);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void endTable() {
|
||||
try {
|
||||
out.write(System.lineSeparator());
|
||||
} catch (IOException ex) {
|
||||
logger.log(Level.WARNING, "Error when closing table: {0}", ex);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return "Files - Text";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getDescription() {
|
||||
return "A tab delimited text file containing information about files in the case.";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getExtension() {
|
||||
return ".txt";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getFilePath() {
|
||||
return FILE_NAME;
|
||||
}
|
||||
}
|
@ -161,7 +161,7 @@ public class ReportBodyFile implements GeneralReportModule {
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
String name = "Body File";
|
||||
String name = "TSK Body File";
|
||||
return name;
|
||||
}
|
||||
|
||||
|
@ -310,7 +310,7 @@ public class ReportExcel implements TableReportModule {
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return "Excel";
|
||||
return "Results - Excel";
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -58,6 +58,7 @@ import org.sleuthkit.datamodel.BlackboardArtifact;
|
||||
import org.sleuthkit.datamodel.BlackboardArtifact.ARTIFACT_TYPE;
|
||||
import org.sleuthkit.datamodel.BlackboardAttribute;
|
||||
import org.sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE;
|
||||
import org.sleuthkit.datamodel.Content;
|
||||
import org.sleuthkit.datamodel.SleuthkitCase;
|
||||
import org.sleuthkit.datamodel.TskCoreException;
|
||||
|
||||
@ -77,13 +78,14 @@ public class ReportGenerator {
|
||||
|
||||
private Map<TableReportModule, ReportProgressPanel> tableProgress;
|
||||
private Map<GeneralReportModule, ReportProgressPanel> generalProgress;
|
||||
private Map<FileReportModule, ReportProgressPanel> fileProgress;
|
||||
|
||||
private String reportPath;
|
||||
private ReportGenerationPanel panel = new ReportGenerationPanel();
|
||||
|
||||
static final String REPORTS_DIR = "Reports";
|
||||
|
||||
ReportGenerator(Map<TableReportModule, Boolean> tableModuleStates, Map<GeneralReportModule, Boolean> generalModuleStates) {
|
||||
ReportGenerator(Map<TableReportModule, Boolean> tableModuleStates, Map<GeneralReportModule, Boolean> generalModuleStates, Map<FileReportModule, Boolean> fileListModuleStates) {
|
||||
// Create the root reports directory path of the form: <CASE DIRECTORY>/Reports/<Case name> <Timestamp>/
|
||||
DateFormat dateFormat = new SimpleDateFormat("MM-dd-yyyy-HH-mm-ss");
|
||||
Date date = new Date();
|
||||
@ -100,7 +102,8 @@ public class ReportGenerator {
|
||||
// Initialize the progress panels
|
||||
generalProgress = new HashMap<>();
|
||||
tableProgress = new HashMap<>();
|
||||
setupProgressPanels(tableModuleStates, generalModuleStates);
|
||||
fileProgress = new HashMap<>();
|
||||
setupProgressPanels(tableModuleStates, generalModuleStates, fileListModuleStates);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -109,7 +112,7 @@ public class ReportGenerator {
|
||||
* @param tableModuleStates the enabled/disabled state of each TableReportModule
|
||||
* @param generalModuleStates the enabled/disabled state of each GeneralReportModule
|
||||
*/
|
||||
private void setupProgressPanels(Map<TableReportModule, Boolean> tableModuleStates, Map<GeneralReportModule, Boolean> generalModuleStates) {
|
||||
private void setupProgressPanels(Map<TableReportModule, Boolean> tableModuleStates, Map<GeneralReportModule, Boolean> generalModuleStates, Map<FileReportModule, Boolean> fileListModuleStates) {
|
||||
if (null != tableModuleStates) {
|
||||
for (Entry<TableReportModule, Boolean> entry : tableModuleStates.entrySet()) {
|
||||
if (entry.getValue()) {
|
||||
@ -127,6 +130,15 @@ public class ReportGenerator {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (null != fileListModuleStates) {
|
||||
for(Entry<FileReportModule, Boolean> entry : fileListModuleStates.entrySet()) {
|
||||
if (entry.getValue()) {
|
||||
FileReportModule module = entry.getKey();
|
||||
fileProgress.put(module, panel.addReport(module.getName(), reportPath + module.getFilePath()));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -183,6 +195,25 @@ public class ReportGenerator {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate the FileReportModule reports in a new SwingWorker.
|
||||
*
|
||||
* @param enabledInfo the Information that should be included about each file
|
||||
* in the report.
|
||||
*/
|
||||
public void generateFileListReports(Map<FileReportDataTypes, Boolean> enabledInfo) {
|
||||
if (!fileProgress.isEmpty() && null != enabledInfo) {
|
||||
List<FileReportDataTypes> enabled = new ArrayList<>();
|
||||
for (Entry<FileReportDataTypes, Boolean> e : enabledInfo.entrySet()) {
|
||||
if(e.getValue()) {
|
||||
enabled.add(e.getKey());
|
||||
}
|
||||
}
|
||||
FileReportsWorker worker = new FileReportsWorker(enabled);
|
||||
worker.execute();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* SwingWorker to generate a report on all GeneralReportModules.
|
||||
*/
|
||||
@ -201,6 +232,91 @@ public class ReportGenerator {
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* SwingWorker to generate a FileReport.
|
||||
*/
|
||||
private class FileReportsWorker extends SwingWorker<Integer, Integer> {
|
||||
private List<FileReportDataTypes> enabledInfo = Arrays.asList(FileReportDataTypes.values());
|
||||
private List<FileReportModule> fileModules = new ArrayList<>();
|
||||
|
||||
FileReportsWorker(List<FileReportDataTypes> enabled) {
|
||||
enabledInfo = enabled;
|
||||
for (Entry<FileReportModule, ReportProgressPanel> entry : fileProgress.entrySet()) {
|
||||
fileModules.add(entry.getKey());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Integer doInBackground() throws Exception {
|
||||
for (FileReportModule module : fileModules) {
|
||||
ReportProgressPanel progress = fileProgress.get(module);
|
||||
if (progress.getStatus() != ReportStatus.CANCELED) {
|
||||
progress.start();
|
||||
progress.updateStatusLabel("Querying database...");
|
||||
}
|
||||
}
|
||||
|
||||
List<AbstractFile> files = getFiles();
|
||||
int numFiles = files.size();
|
||||
for (FileReportModule module : fileModules) {
|
||||
module.startReport(reportPath);
|
||||
module.startTable(enabledInfo);
|
||||
fileProgress.get(module).setIndeterminate(false);
|
||||
fileProgress.get(module).setMaximumProgress(numFiles);
|
||||
}
|
||||
|
||||
int i = 0;
|
||||
// Add files to report.
|
||||
for (AbstractFile file : files) {
|
||||
// Check to see if any reports have been cancelled.
|
||||
if (fileModules.isEmpty()) {
|
||||
break;
|
||||
}
|
||||
// Remove cancelled reports, add files to report otherwise.
|
||||
Iterator<FileReportModule> iter = fileModules.iterator();
|
||||
while (iter.hasNext()) {
|
||||
FileReportModule module = iter.next();
|
||||
ReportProgressPanel progress = fileProgress.get(module);
|
||||
if (progress.getStatus() == ReportStatus.CANCELED) {
|
||||
iter.remove();
|
||||
} else {
|
||||
module.addRow(file, enabledInfo);
|
||||
progress.increment();
|
||||
}
|
||||
|
||||
if ((i % 100) == 0) {
|
||||
progress.updateStatusLabel("Now processing " + file.getName());
|
||||
}
|
||||
}
|
||||
i++;
|
||||
}
|
||||
|
||||
for (FileReportModule module : fileModules) {
|
||||
module.endTable();
|
||||
module.endReport();
|
||||
fileProgress.get(module).complete();
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all files in the image.
|
||||
* @return
|
||||
*/
|
||||
private List<AbstractFile> getFiles() {
|
||||
List<AbstractFile> absFiles;
|
||||
try {
|
||||
SleuthkitCase skCase = Case.getCurrentCase().getSleuthkitCase();
|
||||
absFiles = skCase.findAllFilesWhere("NOT meta_type = 2");
|
||||
return absFiles;
|
||||
} catch (TskCoreException ex) {
|
||||
// TODO
|
||||
return Collections.EMPTY_LIST;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* SwingWorker to generate reports on blackboard artifacts.
|
||||
*/
|
||||
@ -276,27 +392,16 @@ public class ReportGenerator {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Otherwise setup the unsorted list of artifacts, to later be sorted
|
||||
ArtifactComparator c = new ArtifactComparator();
|
||||
List<Entry<BlackboardArtifact, List<BlackboardAttribute>>> unsortedArtifacts = new ArrayList<>();
|
||||
try {
|
||||
// For every artifact of the current type, add it and it's attributes to a list
|
||||
for (BlackboardArtifact artifact : skCase.getBlackboardArtifacts(type)) {
|
||||
try {
|
||||
unsortedArtifacts.add(new ArtifactEntry<BlackboardArtifact, List<BlackboardAttribute>>(artifact, skCase.getBlackboardAttributes(artifact)));
|
||||
} catch (TskCoreException ex) {
|
||||
logger.log(Level.SEVERE, "Failed to get Blackboard Attributes when generating report.", ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (TskCoreException ex) {
|
||||
logger.log(Level.SEVERE, "Failed to get Blackboard Artifacts when generating report.", ex);
|
||||
}
|
||||
List<ArtifactData> unsortedArtifacts = getFilteredArtifacts(type, tagNamesFilter);
|
||||
|
||||
if (unsortedArtifacts.isEmpty()) {
|
||||
// Don't report on this artifact type if there are no results
|
||||
continue;
|
||||
}
|
||||
// The most efficient way to sort all the Artifacts is to add them to a List, and then
|
||||
// sort that List based off a Comparator. Adding to a TreeMap/Set/List sorts the list
|
||||
// each time an element is added, which adds unnecessary overhead if we only need it sorted once.
|
||||
Collections.sort(unsortedArtifacts, c);
|
||||
Collections.sort(unsortedArtifacts);
|
||||
|
||||
// Get the column headers appropriate for the artifact type.
|
||||
/* @@@ BC: Seems like a better design here woudl be to have a method that
|
||||
@ -310,11 +415,10 @@ public class ReportGenerator {
|
||||
MessageNotifyUtil.Notify.show("Skipping artifact type " + type + " in reports", "Unknown columns to report on", MessageNotifyUtil.MessageType.ERROR);
|
||||
continue;
|
||||
}
|
||||
|
||||
// For every module start a new data type and table for the current artifact type.
|
||||
|
||||
for (TableReportModule module : tableModules) {
|
||||
tableProgress.get(module).updateStatusLabel("Now processing " + type.getDisplayName() + "...");
|
||||
|
||||
|
||||
// This is a temporary workaround to avoid modifying the TableReportModule interface.
|
||||
if (module instanceof ReportHTML) {
|
||||
ReportHTML htmlReportModule = (ReportHTML)module;
|
||||
@ -332,21 +436,18 @@ public class ReportGenerator {
|
||||
}
|
||||
}
|
||||
|
||||
boolean msgSent = false;
|
||||
// Add a row to the table for every artifact of the current type that satisfies the tags filter, if any.
|
||||
for (Entry<BlackboardArtifact, List<BlackboardAttribute>> artifactEntry : unsortedArtifacts) {
|
||||
// Get any tags associated with the artifact and apply the tags filter, if any.
|
||||
HashSet<String> tags = Tags.getUniqueTagNamesForArtifact(artifactEntry.getKey());
|
||||
if (failsTagFilter(tags, tagNamesFilter)) {
|
||||
continue;
|
||||
}
|
||||
boolean msgSent = false;
|
||||
for(ArtifactData artifactData : unsortedArtifacts) {
|
||||
HashSet<String> tags = artifactData.getTags();
|
||||
|
||||
String tagsList = makeCommaSeparatedList(tags);
|
||||
|
||||
// Add the row data to all of the reports.
|
||||
for (TableReportModule module : tableModules) {
|
||||
|
||||
// Get the row data for this type of artifact.
|
||||
List<String> rowData;
|
||||
rowData = getArtifactRow(artifactEntry, module);
|
||||
rowData = getArtifactRow(artifactData, module);
|
||||
if (rowData == null) {
|
||||
if (msgSent == false) {
|
||||
MessageNotifyUtil.Notify.show("Skipping artifact rows for type " + type + " in reports", "Unknown columns to report on", MessageNotifyUtil.MessageType.ERROR);
|
||||
@ -355,8 +456,8 @@ public class ReportGenerator {
|
||||
continue;
|
||||
}
|
||||
// Add the list of tag names if the artifact is not itself as tag.
|
||||
if (artifactEntry.getKey().getArtifactTypeID() != ARTIFACT_TYPE.TSK_TAG_ARTIFACT.getTypeID() &&
|
||||
artifactEntry.getKey().getArtifactTypeID() != ARTIFACT_TYPE.TSK_TAG_FILE.getTypeID())
|
||||
if (artifactData.getArtifact().getArtifactTypeID() != ARTIFACT_TYPE.TSK_TAG_ARTIFACT.getTypeID() &&
|
||||
artifactData.getArtifact().getArtifactTypeID() != ARTIFACT_TYPE.TSK_TAG_FILE.getTypeID())
|
||||
{
|
||||
rowData.add(tagsList);
|
||||
}
|
||||
@ -364,7 +465,7 @@ public class ReportGenerator {
|
||||
// This is a temporary workaround to avoid modifying the TableReportModule interface.
|
||||
if (module instanceof ReportHTML) {
|
||||
ReportHTML htmlReportModule = (ReportHTML)module;
|
||||
htmlReportModule.addRow(rowData, artifactEntry.getKey());
|
||||
htmlReportModule.addRow(rowData, artifactData.getArtifact());
|
||||
}
|
||||
else {
|
||||
module.addRow(rowData);
|
||||
@ -400,6 +501,35 @@ public class ReportGenerator {
|
||||
filteredTags.retainAll(tagsFilter);
|
||||
return filteredTags.isEmpty();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a List of the artifacts and data of the given type that pass the given Tag Filter.
|
||||
*
|
||||
* @param type The artifact type to get
|
||||
* @param tagNamesFilter The tag names that should be included.
|
||||
* @return a list of the filtered tags.
|
||||
*/
|
||||
private List<ArtifactData> getFilteredArtifacts(ARTIFACT_TYPE type, HashSet<String> tagNamesFilter) {
|
||||
List<ArtifactData> artifacts = new ArrayList<>();
|
||||
try {
|
||||
// For every artifact of the current type, add it and it's attributes to a list
|
||||
for (BlackboardArtifact artifact : skCase.getBlackboardArtifacts(type)) {
|
||||
HashSet<String> tags = Tags.getUniqueTagNamesForArtifact(artifact);
|
||||
if(failsTagFilter(tags, tagNamesFilter)) {
|
||||
continue;
|
||||
}
|
||||
try {
|
||||
artifacts.add(new ArtifactData(artifact, skCase.getBlackboardAttributes(artifact), tags));
|
||||
} catch (TskCoreException ex) {
|
||||
logger.log(Level.SEVERE, "Failed to get Blackboard Attributes when generating report.", ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (TskCoreException ex) {
|
||||
logger.log(Level.SEVERE, "Failed to get Blackboard Artifacts when generating report.", ex);
|
||||
}
|
||||
return artifacts;
|
||||
}
|
||||
|
||||
/**
|
||||
* Write the keyword hits to the provided TableReportModules.
|
||||
@ -857,10 +987,10 @@ public class ReportGenerator {
|
||||
* @return List<String> row values
|
||||
* @throws TskCoreException
|
||||
*/
|
||||
private List<String> getArtifactRow(Entry<BlackboardArtifact, List<BlackboardAttribute>> entry, TableReportModule module) throws TskCoreException {
|
||||
Map<Integer, String> attributes = getMappedAttributes(entry.getValue(), module);
|
||||
private List<String> getArtifactRow(ArtifactData artifactData, TableReportModule module) throws TskCoreException {
|
||||
Map<Integer, String> attributes = getMappedAttributes(artifactData.getAttributes(), module);
|
||||
|
||||
BlackboardArtifact.ARTIFACT_TYPE type = BlackboardArtifact.ARTIFACT_TYPE.fromID(entry.getKey().getArtifactTypeID());
|
||||
BlackboardArtifact.ARTIFACT_TYPE type = BlackboardArtifact.ARTIFACT_TYPE.fromID(artifactData.getArtifact().getArtifactTypeID());
|
||||
|
||||
switch (type) {
|
||||
case TSK_WEB_BOOKMARK:
|
||||
@ -869,7 +999,7 @@ public class ReportGenerator {
|
||||
bookmark.add(attributes.get(ATTRIBUTE_TYPE.TSK_TITLE.getTypeID()));
|
||||
bookmark.add(attributes.get(ATTRIBUTE_TYPE.TSK_DATETIME_ACCESSED.getTypeID()));
|
||||
bookmark.add(attributes.get(ATTRIBUTE_TYPE.TSK_PROG_NAME.getTypeID()));
|
||||
bookmark.add(getFileUniquePath(entry.getKey().getObjectID()));
|
||||
bookmark.add(getFileUniquePath(artifactData.getObjectID()));
|
||||
return bookmark;
|
||||
case TSK_WEB_COOKIE:
|
||||
List<String> cookie = new ArrayList<>();
|
||||
@ -878,7 +1008,7 @@ public class ReportGenerator {
|
||||
cookie.add(attributes.get(ATTRIBUTE_TYPE.TSK_NAME.getTypeID()));
|
||||
cookie.add(attributes.get(ATTRIBUTE_TYPE.TSK_VALUE.getTypeID()));
|
||||
cookie.add(attributes.get(ATTRIBUTE_TYPE.TSK_PROG_NAME.getTypeID()));
|
||||
cookie.add(getFileUniquePath(entry.getKey().getObjectID()));
|
||||
cookie.add(getFileUniquePath(artifactData.getObjectID()));
|
||||
return cookie;
|
||||
case TSK_WEB_HISTORY:
|
||||
List<String> history = new ArrayList<>();
|
||||
@ -887,7 +1017,7 @@ public class ReportGenerator {
|
||||
history.add(attributes.get(ATTRIBUTE_TYPE.TSK_REFERRER.getTypeID()));
|
||||
history.add(attributes.get(ATTRIBUTE_TYPE.TSK_NAME.getTypeID()));
|
||||
history.add(attributes.get(ATTRIBUTE_TYPE.TSK_PROG_NAME.getTypeID()));
|
||||
history.add(getFileUniquePath(entry.getKey().getObjectID()));
|
||||
history.add(getFileUniquePath(artifactData.getObjectID()));
|
||||
return history;
|
||||
case TSK_WEB_DOWNLOAD:
|
||||
List<String> download = new ArrayList<>();
|
||||
@ -895,25 +1025,25 @@ public class ReportGenerator {
|
||||
download.add(attributes.get(ATTRIBUTE_TYPE.TSK_URL.getTypeID()));
|
||||
download.add(attributes.get(ATTRIBUTE_TYPE.TSK_DATETIME_ACCESSED.getTypeID()));
|
||||
download.add(attributes.get(ATTRIBUTE_TYPE.TSK_PROG_NAME.getTypeID()));
|
||||
download.add(getFileUniquePath(entry.getKey().getObjectID()));
|
||||
download.add(getFileUniquePath(artifactData.getObjectID()));
|
||||
return download;
|
||||
case TSK_RECENT_OBJECT:
|
||||
List<String> recent = new ArrayList<>();
|
||||
recent.add(attributes.get(ATTRIBUTE_TYPE.TSK_PATH.getTypeID()));
|
||||
recent.add(getFileUniquePath(entry.getKey().getObjectID()));
|
||||
recent.add(getFileUniquePath(artifactData.getObjectID()));
|
||||
return recent;
|
||||
case TSK_INSTALLED_PROG:
|
||||
List<String> installed = new ArrayList<>();
|
||||
installed.add(attributes.get(ATTRIBUTE_TYPE.TSK_PROG_NAME.getTypeID()));
|
||||
installed.add(attributes.get(ATTRIBUTE_TYPE.TSK_DATETIME.getTypeID()));
|
||||
installed.add(getFileUniquePath(entry.getKey().getObjectID()));
|
||||
installed.add(getFileUniquePath(artifactData.getObjectID()));
|
||||
return installed;
|
||||
case TSK_DEVICE_ATTACHED:
|
||||
List<String> devices = new ArrayList<>();
|
||||
devices.add(attributes.get(ATTRIBUTE_TYPE.TSK_DEVICE_MODEL.getTypeID()));
|
||||
devices.add(attributes.get(ATTRIBUTE_TYPE.TSK_DEVICE_ID.getTypeID()));
|
||||
devices.add(attributes.get(ATTRIBUTE_TYPE.TSK_DATETIME.getTypeID()));
|
||||
devices.add(getFileUniquePath(entry.getKey().getObjectID()));
|
||||
devices.add(getFileUniquePath(artifactData.getObjectID()));
|
||||
return devices;
|
||||
case TSK_WEB_SEARCH_QUERY:
|
||||
List<String> search = new ArrayList<>();
|
||||
@ -921,7 +1051,7 @@ public class ReportGenerator {
|
||||
search.add(attributes.get(ATTRIBUTE_TYPE.TSK_DOMAIN.getTypeID()));
|
||||
search.add(attributes.get(ATTRIBUTE_TYPE.TSK_DATETIME_ACCESSED.getTypeID()));
|
||||
search.add(attributes.get(ATTRIBUTE_TYPE.TSK_PROG_NAME.getTypeID()));
|
||||
search.add(getFileUniquePath(entry.getKey().getObjectID()));
|
||||
search.add(getFileUniquePath(artifactData.getObjectID()));
|
||||
return search;
|
||||
case TSK_METADATA_EXIF:
|
||||
List<String> exif = new ArrayList<>();
|
||||
@ -930,11 +1060,11 @@ public class ReportGenerator {
|
||||
exif.add(attributes.get(ATTRIBUTE_TYPE.TSK_DEVICE_MODEL.getTypeID()));
|
||||
exif.add(attributes.get(ATTRIBUTE_TYPE.TSK_GEO_LATITUDE.getTypeID()));
|
||||
exif.add(attributes.get(ATTRIBUTE_TYPE.TSK_GEO_LONGITUDE.getTypeID()));
|
||||
exif.add(getFileUniquePath(entry.getKey().getObjectID()));
|
||||
exif.add(getFileUniquePath(artifactData.getObjectID()));
|
||||
return exif;
|
||||
case TSK_TAG_FILE:
|
||||
List<String> taggedFileRow = new ArrayList<>();
|
||||
AbstractFile taggedFile = getAbstractFile(entry.getKey().getObjectID());
|
||||
AbstractFile taggedFile = getAbstractFile(artifactData.getObjectID());
|
||||
if (taggedFile != null) {
|
||||
taggedFileRow.add(taggedFile.getUniquePath());
|
||||
} else {
|
||||
@ -946,7 +1076,7 @@ public class ReportGenerator {
|
||||
case TSK_TAG_ARTIFACT:
|
||||
List<String> taggedArtifactRow = new ArrayList<>();
|
||||
String taggedArtifactType = "";
|
||||
for (BlackboardAttribute attr : entry.getValue()) {
|
||||
for (BlackboardAttribute attr : artifactData.getAttributes()) {
|
||||
if (attr.getAttributeTypeID() == ATTRIBUTE_TYPE.TSK_TAGGED_ARTIFACT.getTypeID()) {
|
||||
BlackboardArtifact taggedArtifact = getArtifact(attr.getValueLong());
|
||||
if (taggedArtifact != null) {
|
||||
@ -958,7 +1088,7 @@ public class ReportGenerator {
|
||||
taggedArtifactRow.add(taggedArtifactType);
|
||||
taggedArtifactRow.add(attributes.get(ATTRIBUTE_TYPE.TSK_TAG_NAME.getTypeID()));
|
||||
taggedArtifactRow.add(attributes.get(ATTRIBUTE_TYPE.TSK_COMMENT.getTypeID()));
|
||||
AbstractFile sourceFile = getAbstractFile(entry.getKey().getObjectID());
|
||||
AbstractFile sourceFile = getAbstractFile(artifactData.getObjectID());
|
||||
if (sourceFile != null) {
|
||||
taggedArtifactRow.add(sourceFile.getUniquePath());
|
||||
} else {
|
||||
@ -973,7 +1103,7 @@ public class ReportGenerator {
|
||||
contact.add(attributes.get(ATTRIBUTE_TYPE.TSK_PHONE_NUMBER_OFFICE.getTypeID()));
|
||||
contact.add(attributes.get(ATTRIBUTE_TYPE.TSK_PHONE_NUMBER_MOBILE.getTypeID()));
|
||||
contact.add(attributes.get(ATTRIBUTE_TYPE.TSK_EMAIL.getTypeID()));
|
||||
contact.add(getFileUniquePath(entry.getKey().getObjectID()));
|
||||
contact.add(getFileUniquePath(artifactData.getObjectID()));
|
||||
return contact;
|
||||
case TSK_MESSAGE:
|
||||
List<String> message = new ArrayList<>();
|
||||
@ -986,7 +1116,7 @@ public class ReportGenerator {
|
||||
message.add(attributes.get(ATTRIBUTE_TYPE.TSK_EMAIL_TO.getTypeID()));
|
||||
message.add(attributes.get(ATTRIBUTE_TYPE.TSK_SUBJECT.getTypeID()));
|
||||
message.add(attributes.get(ATTRIBUTE_TYPE.TSK_TEXT.getTypeID()));
|
||||
message.add(getFileUniquePath(entry.getKey().getObjectID()));
|
||||
message.add(getFileUniquePath(artifactData.getObjectID()));
|
||||
return message;
|
||||
case TSK_CALLLOG:
|
||||
List<String> call_log = new ArrayList<>();
|
||||
@ -994,7 +1124,7 @@ public class ReportGenerator {
|
||||
call_log.add(attributes.get(ATTRIBUTE_TYPE.TSK_PHONE_NUMBER.getTypeID()));
|
||||
call_log.add(attributes.get(ATTRIBUTE_TYPE.TSK_DATETIME.getTypeID()));
|
||||
call_log.add(attributes.get(ATTRIBUTE_TYPE.TSK_DIRECTION.getTypeID()));
|
||||
call_log.add(getFileUniquePath(entry.getKey().getObjectID()));
|
||||
call_log.add(getFileUniquePath(artifactData.getObjectID()));
|
||||
return call_log;
|
||||
case TSK_CALENDAR_ENTRY:
|
||||
List<String> calEntry = new ArrayList<>();
|
||||
@ -1003,21 +1133,21 @@ public class ReportGenerator {
|
||||
calEntry.add(attributes.get(ATTRIBUTE_TYPE.TSK_DATETIME_START.getTypeID()));
|
||||
calEntry.add(attributes.get(ATTRIBUTE_TYPE.TSK_DATETIME_END.getTypeID()));
|
||||
calEntry.add(attributes.get(ATTRIBUTE_TYPE.TSK_LOCATION.getTypeID()));
|
||||
calEntry.add(getFileUniquePath(entry.getKey().getObjectID()));
|
||||
calEntry.add(getFileUniquePath(artifactData.getObjectID()));
|
||||
return calEntry;
|
||||
case TSK_SPEED_DIAL_ENTRY:
|
||||
List<String> speedDialEntry = new ArrayList<String>();
|
||||
speedDialEntry.add(attributes.get(ATTRIBUTE_TYPE.TSK_SHORTCUT.getTypeID()));
|
||||
speedDialEntry.add(attributes.get(ATTRIBUTE_TYPE.TSK_NAME_PERSON.getTypeID()));
|
||||
speedDialEntry.add(attributes.get(ATTRIBUTE_TYPE.TSK_PHONE_NUMBER.getTypeID()));
|
||||
speedDialEntry.add(getFileUniquePath(entry.getKey().getObjectID()));
|
||||
speedDialEntry.add(getFileUniquePath(artifactData.getObjectID()));
|
||||
return speedDialEntry;
|
||||
case TSK_BLUETOOTH_PAIRING:
|
||||
List<String> bluetoothEntry = new ArrayList<String>();
|
||||
bluetoothEntry.add(attributes.get(ATTRIBUTE_TYPE.TSK_DEVICE_NAME.getTypeID()));
|
||||
bluetoothEntry.add(attributes.get(ATTRIBUTE_TYPE.TSK_DEVICE_ID.getTypeID()));
|
||||
bluetoothEntry.add(attributes.get(ATTRIBUTE_TYPE.TSK_DATETIME.getTypeID()));
|
||||
bluetoothEntry.add(getFileUniquePath(entry.getKey().getObjectID()));
|
||||
bluetoothEntry.add(getFileUniquePath(artifactData.getObjectID()));
|
||||
return bluetoothEntry;
|
||||
case TSK_GPS_TRACKPOINT:
|
||||
List<String> gpsTrackpoint = new ArrayList<String>();
|
||||
@ -1027,7 +1157,7 @@ public class ReportGenerator {
|
||||
gpsTrackpoint.add(attributes.get(ATTRIBUTE_TYPE.TSK_NAME.getTypeID()));
|
||||
gpsTrackpoint.add(attributes.get(ATTRIBUTE_TYPE.TSK_LOCATION.getTypeID()));
|
||||
gpsTrackpoint.add(attributes.get(ATTRIBUTE_TYPE.TSK_DATETIME.getTypeID()));
|
||||
gpsTrackpoint.add(getFileUniquePath(entry.getKey().getObjectID()));
|
||||
gpsTrackpoint.add(getFileUniquePath(artifactData.getObjectID()));
|
||||
return gpsTrackpoint;
|
||||
case TSK_GPS_BOOKMARK:
|
||||
List<String> gpsBookmarkEntry = new ArrayList<String>();
|
||||
@ -1037,7 +1167,7 @@ public class ReportGenerator {
|
||||
gpsBookmarkEntry.add(attributes.get(ATTRIBUTE_TYPE.TSK_NAME.getTypeID()));
|
||||
gpsBookmarkEntry.add(attributes.get(ATTRIBUTE_TYPE.TSK_LOCATION.getTypeID()));
|
||||
gpsBookmarkEntry.add(attributes.get(ATTRIBUTE_TYPE.TSK_DATETIME.getTypeID()));
|
||||
gpsBookmarkEntry.add(getFileUniquePath(entry.getKey().getObjectID()));
|
||||
gpsBookmarkEntry.add(getFileUniquePath(artifactData.getObjectID()));
|
||||
return gpsBookmarkEntry;
|
||||
case TSK_GPS_LAST_KNOWN_LOCATION:
|
||||
List<String> gpsLastLocation = new ArrayList<String>();
|
||||
@ -1047,7 +1177,7 @@ public class ReportGenerator {
|
||||
gpsLastLocation.add(attributes.get(ATTRIBUTE_TYPE.TSK_NAME.getTypeID()));
|
||||
gpsLastLocation.add(attributes.get(ATTRIBUTE_TYPE.TSK_LOCATION.getTypeID()));
|
||||
gpsLastLocation.add(attributes.get(ATTRIBUTE_TYPE.TSK_DATETIME.getTypeID()));
|
||||
gpsLastLocation.add(getFileUniquePath(entry.getKey().getObjectID()));
|
||||
gpsLastLocation.add(getFileUniquePath(artifactData.getObjectID()));
|
||||
return gpsLastLocation;
|
||||
case TSK_GPS_SEARCH:
|
||||
List<String> gpsSearch = new ArrayList<String>();
|
||||
@ -1057,7 +1187,7 @@ public class ReportGenerator {
|
||||
gpsSearch.add(attributes.get(ATTRIBUTE_TYPE.TSK_NAME.getTypeID()));
|
||||
gpsSearch.add(attributes.get(ATTRIBUTE_TYPE.TSK_LOCATION.getTypeID()));
|
||||
gpsSearch.add(attributes.get(ATTRIBUTE_TYPE.TSK_DATETIME.getTypeID()));
|
||||
gpsSearch.add(getFileUniquePath(entry.getKey().getObjectID()));
|
||||
gpsSearch.add(getFileUniquePath(artifactData.getObjectID()));
|
||||
return gpsSearch;
|
||||
case TSK_SERVICE_ACCOUNT:
|
||||
List<String> appAccount = new ArrayList<String>();
|
||||
@ -1071,13 +1201,13 @@ public class ReportGenerator {
|
||||
appAccount.add(attributes.get(ATTRIBUTE_TYPE.TSK_DESCRIPTION.getTypeID()));
|
||||
appAccount.add(attributes.get(ATTRIBUTE_TYPE.TSK_EMAIL_REPLYTO.getTypeID()));
|
||||
appAccount.add(attributes.get(ATTRIBUTE_TYPE.TSK_SERVER_NAME.getTypeID()));
|
||||
appAccount.add(getFileUniquePath(entry.getKey().getObjectID()));
|
||||
appAccount.add(getFileUniquePath(artifactData.getObjectID()));
|
||||
return appAccount;
|
||||
case TSK_TOOL_OUTPUT:
|
||||
List<String> row = new ArrayList<>();
|
||||
row.add(attributes.get(ATTRIBUTE_TYPE.TSK_PROG_NAME.getTypeID()));
|
||||
row.add(attributes.get(ATTRIBUTE_TYPE.TSK_TEXT.getTypeID()));
|
||||
row.add(getFileUniquePath(entry.getKey().getObjectID()));
|
||||
row.add(getFileUniquePath(artifactData.getObjectID()));
|
||||
return row;
|
||||
}
|
||||
return null;
|
||||
@ -1144,51 +1274,44 @@ public class ReportGenerator {
|
||||
}
|
||||
|
||||
/**
|
||||
* Map.Entry for BlackboardArtifacts and lists of BlackboardAttributes.
|
||||
*
|
||||
* @param <K> BlackboardArtifact
|
||||
* @param <V> List<BlackboardAttribute>
|
||||
* Container class that holds data about an Artifact to eliminate duplicate
|
||||
* calls to the Sleuthkit database.
|
||||
*/
|
||||
private class ArtifactEntry<K, V> implements Map.Entry<BlackboardArtifact, List<BlackboardAttribute>> {
|
||||
BlackboardArtifact artifact;
|
||||
List<BlackboardAttribute> attributes;
|
||||
private class ArtifactData implements Comparable<ArtifactData> {
|
||||
private BlackboardArtifact artifact;
|
||||
private List<BlackboardAttribute> attributes;
|
||||
private HashSet<String> tags;
|
||||
|
||||
private ArtifactEntry(BlackboardArtifact artifact, List<BlackboardAttribute> attributes) {
|
||||
ArtifactData(BlackboardArtifact artifact, List<BlackboardAttribute> attrs, HashSet<String> tags) {
|
||||
this.artifact = artifact;
|
||||
this.attributes = attributes;
|
||||
this.attributes = attrs;
|
||||
this.tags = tags;
|
||||
}
|
||||
|
||||
public BlackboardArtifact getArtifact() { return artifact; }
|
||||
|
||||
public List<BlackboardAttribute> getAttributes() { return attributes; }
|
||||
|
||||
public HashSet<String> getTags() { return tags; }
|
||||
|
||||
public long getArtifactID() { return artifact.getArtifactID(); }
|
||||
|
||||
public long getObjectID() { return artifact.getObjectID(); }
|
||||
|
||||
@Override
|
||||
public BlackboardArtifact getKey() {
|
||||
return artifact;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<BlackboardAttribute> getValue() {
|
||||
return attributes;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<BlackboardAttribute> setValue(List<BlackboardAttribute> value) {
|
||||
List<BlackboardAttribute> old = attributes;
|
||||
attributes = value;
|
||||
return old;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Compares entries of BlackboardArtifacts and lists of BlackboardAttributes, sorting by
|
||||
* the first attribute both artifacts have in common. If all attributes are the same, they are
|
||||
* assumed duplicates, and they are sorted on artifact ID. Should only be used on artifacts
|
||||
* of similar types.
|
||||
*/
|
||||
private class ArtifactComparator implements Comparator<Entry<BlackboardArtifact, List<BlackboardAttribute>>> {
|
||||
@Override
|
||||
public int compare(Entry<BlackboardArtifact, List<BlackboardAttribute>> art1, Entry<BlackboardArtifact, List<BlackboardAttribute>> art2) {
|
||||
/**
|
||||
* Compares ArtifactData objects by the first attribute they have in
|
||||
* common in their List<BlackboardAttribute>.
|
||||
*
|
||||
* If all attributes are the same, they are assumed duplicates and are
|
||||
* compared by their artifact id. Should only be used with attributes
|
||||
* of the same type.
|
||||
*/
|
||||
public int compareTo(ArtifactData data) {
|
||||
// Get all the attributes for each artifact
|
||||
int size = ATTRIBUTE_TYPE.values().length;
|
||||
Map<Integer, String> att1 = getMappedAttributes(art1.getValue());
|
||||
Map<Integer, String> att2 = getMappedAttributes(art2.getValue());
|
||||
Map<Integer, String> att1 = getMappedAttributes(this.attributes);
|
||||
Map<Integer, String> att2 = getMappedAttributes(data.getAttributes());
|
||||
// Compare the attributes one-by-one looking for differences
|
||||
for(int i=0; i < size; i++) {
|
||||
String a1 = att1.get(i);
|
||||
@ -1198,7 +1321,7 @@ public class ReportGenerator {
|
||||
}
|
||||
}
|
||||
// If all attributes are the same, they're most likely duplicates so sort by artifact ID
|
||||
return ((Long)art1.getKey().getArtifactID()).compareTo((Long)art2.getKey().getArtifactID());
|
||||
return ((Long)this.getArtifactID()).compareTo((Long)data.getArtifactID());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -665,7 +665,7 @@ public class ReportHTML implements TableReportModule {
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return "HTML";
|
||||
return "Results - HTML";
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -24,10 +24,10 @@
|
||||
<Group type="102" attributes="0">
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<Component id="reportModulesLabel" alignment="0" min="-2" max="-2" attributes="0"/>
|
||||
<Component id="modulesScrollPane" alignment="0" min="-2" pref="186" max="-2" attributes="0"/>
|
||||
<Component id="reportModulesLabel" min="-2" max="-2" attributes="0"/>
|
||||
<Component id="modulesScrollPane" min="-2" pref="190" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
<EmptySpace min="-2" pref="10" max="-2" attributes="0"/>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<Component id="configurationPanel" max="32767" attributes="0"/>
|
||||
<Component id="descriptionScrollPane" max="32767" attributes="0"/>
|
||||
@ -43,12 +43,12 @@
|
||||
<Component id="reportModulesLabel" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<Component id="modulesScrollPane" pref="208" max="32767" attributes="0"/>
|
||||
<Group type="102" attributes="0">
|
||||
<Component id="configurationPanel" max="32767" attributes="0"/>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Component id="descriptionScrollPane" min="-2" pref="32" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
<Component id="modulesScrollPane" max="32767" attributes="0"/>
|
||||
</Group>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
</Group>
|
||||
@ -56,30 +56,6 @@
|
||||
</DimensionLayout>
|
||||
</Layout>
|
||||
<SubComponents>
|
||||
<Container class="javax.swing.JScrollPane" name="modulesScrollPane">
|
||||
<AuxValues>
|
||||
<AuxValue name="autoScrollPane" type="java.lang.Boolean" value="true"/>
|
||||
</AuxValues>
|
||||
|
||||
<Layout class="org.netbeans.modules.form.compat2.layouts.support.JScrollPaneSupportLayout"/>
|
||||
<SubComponents>
|
||||
<Component class="javax.swing.JTable" name="modulesTable">
|
||||
<Properties>
|
||||
<Property name="background" type="java.awt.Color" editor="org.netbeans.beaninfo.editors.ColorEditor">
|
||||
<Color blue="f0" green="f0" red="f0" type="rgb"/>
|
||||
</Property>
|
||||
<Property name="model" type="javax.swing.table.TableModel" editor="org.netbeans.modules.form.editors2.TableModelEditor">
|
||||
<Table columnCount="0" rowCount="0"/>
|
||||
</Property>
|
||||
<Property name="showHorizontalLines" type="boolean" value="false"/>
|
||||
<Property name="showVerticalLines" type="boolean" value="false"/>
|
||||
<Property name="tableHeader" type="javax.swing.table.JTableHeader" editor="org.netbeans.modules.form.editors2.JTableHeaderEditor">
|
||||
<TableHeader reorderingAllowed="true" resizingAllowed="true"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
</Component>
|
||||
</SubComponents>
|
||||
</Container>
|
||||
<Component class="javax.swing.JLabel" name="reportModulesLabel">
|
||||
<Properties>
|
||||
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||
@ -106,7 +82,7 @@
|
||||
</DimensionLayout>
|
||||
<DimensionLayout dim="1">
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<EmptySpace min="0" pref="0" max="32767" attributes="0"/>
|
||||
<EmptySpace min="0" pref="168" max="32767" attributes="0"/>
|
||||
</Group>
|
||||
</DimensionLayout>
|
||||
</Layout>
|
||||
@ -135,5 +111,30 @@
|
||||
</Component>
|
||||
</SubComponents>
|
||||
</Container>
|
||||
<Container class="javax.swing.JScrollPane" name="modulesScrollPane">
|
||||
<AuxValues>
|
||||
<AuxValue name="autoScrollPane" type="java.lang.Boolean" value="true"/>
|
||||
</AuxValues>
|
||||
|
||||
<Layout class="org.netbeans.modules.form.compat2.layouts.support.JScrollPaneSupportLayout"/>
|
||||
<SubComponents>
|
||||
<Component class="javax.swing.JList" name="modulesJList">
|
||||
<Properties>
|
||||
<Property name="background" type="java.awt.Color" editor="org.netbeans.beaninfo.editors.ColorEditor">
|
||||
<Color blue="f0" green="f0" red="f0" type="rgb"/>
|
||||
</Property>
|
||||
<Property name="model" type="javax.swing.ListModel" editor="org.netbeans.modules.form.editors2.ListModelEditor">
|
||||
<StringArray count="5">
|
||||
<StringItem index="0" value="Item 1"/>
|
||||
<StringItem index="1" value="Item 2"/>
|
||||
<StringItem index="2" value="Item 3"/>
|
||||
<StringItem index="3" value="Item 4"/>
|
||||
<StringItem index="4" value="Item 5"/>
|
||||
</StringArray>
|
||||
</Property>
|
||||
</Properties>
|
||||
</Component>
|
||||
</SubComponents>
|
||||
</Container>
|
||||
</SubComponents>
|
||||
</Form>
|
||||
|
@ -19,76 +19,72 @@
|
||||
package org.sleuthkit.autopsy.report;
|
||||
|
||||
import java.awt.BorderLayout;
|
||||
import java.awt.Component;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
import javax.swing.JList;
|
||||
import javax.swing.JPanel;
|
||||
import javax.swing.JRadioButton;
|
||||
import javax.swing.ListCellRenderer;
|
||||
import javax.swing.ListSelectionModel;
|
||||
import javax.swing.event.ListSelectionEvent;
|
||||
import javax.swing.event.ListSelectionListener;
|
||||
import javax.swing.table.AbstractTableModel;
|
||||
import javax.swing.table.TableColumn;
|
||||
import org.openide.util.Lookup;
|
||||
import org.sleuthkit.autopsy.coreutils.Logger;
|
||||
|
||||
public final class ReportVisualPanel1 extends JPanel {
|
||||
public final class ReportVisualPanel1 extends JPanel implements ListSelectionListener {
|
||||
private static final Logger logger = Logger.getLogger(ReportVisualPanel1.class.getName());
|
||||
private ReportWizardPanel1 wizPanel;
|
||||
|
||||
private Map<TableReportModule, Boolean> tableModuleStates = new LinkedHashMap<TableReportModule, Boolean>();
|
||||
private Map<GeneralReportModule, Boolean> generalModuleStates = new LinkedHashMap<GeneralReportModule, Boolean>();
|
||||
private List<TableReportModule> tableModules = new ArrayList<TableReportModule>();
|
||||
private List<GeneralReportModule> generalModules = new ArrayList<GeneralReportModule>();
|
||||
|
||||
private ModulesTableModel modulesModel;
|
||||
private ModuleSelectionListener modulesListener;
|
||||
private List<ReportModule> modules = new ArrayList<>();
|
||||
private List<GeneralReportModule> generalModules = new ArrayList<>();
|
||||
private List<TableReportModule> tableModules = new ArrayList<>();
|
||||
private List<FileReportModule> fileModules = new ArrayList<>();
|
||||
private Integer selectedIndex;
|
||||
|
||||
/**
|
||||
* Creates new form ReportVisualPanel1
|
||||
*/
|
||||
public ReportVisualPanel1(ReportWizardPanel1 wizPanel) {
|
||||
initComponents();
|
||||
initModules();
|
||||
this.wizPanel = wizPanel;
|
||||
initComponents();
|
||||
configurationPanel.setLayout(new BorderLayout());
|
||||
descriptionTextPane.setEditable(false);
|
||||
modulesTable.setRowSelectionInterval(0, 0);
|
||||
initModules();
|
||||
}
|
||||
|
||||
// Initialize the list of ReportModules
|
||||
private void initModules() {
|
||||
for(TableReportModule module : Lookup.getDefault().lookupAll(TableReportModule.class)) {
|
||||
if(module.getName().equals("HTML")) {
|
||||
tableModuleStates.put(module, Boolean.TRUE);
|
||||
} else {
|
||||
tableModuleStates.put(module, Boolean.FALSE);
|
||||
}
|
||||
for (TableReportModule module : Lookup.getDefault().lookupAll(TableReportModule.class)) {
|
||||
tableModules.add(module);
|
||||
modules.add(module);
|
||||
}
|
||||
for(GeneralReportModule module : Lookup.getDefault().lookupAll(GeneralReportModule.class)) {
|
||||
generalModuleStates.put(module, Boolean.FALSE);
|
||||
|
||||
for (GeneralReportModule module : Lookup.getDefault().lookupAll(GeneralReportModule.class)) {
|
||||
generalModules.add(module);
|
||||
modules.add(module);
|
||||
}
|
||||
|
||||
modulesModel = new ModulesTableModel();
|
||||
modulesListener = new ModuleSelectionListener();
|
||||
modulesTable.setModel(modulesModel);
|
||||
modulesTable.getSelectionModel().addListSelectionListener(modulesListener);
|
||||
modulesTable.setTableHeader(null);
|
||||
modulesTable.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
|
||||
modulesTable.setRowHeight(modulesTable.getRowHeight() + 5);
|
||||
for (FileReportModule module : Lookup.getDefault().lookupAll(FileReportModule.class)) {
|
||||
fileModules.add(module);
|
||||
modules.add(module);
|
||||
}
|
||||
|
||||
int width = modulesScrollPane.getPreferredSize().width;
|
||||
for (int i = 0; i < modulesTable.getColumnCount(); i++) {
|
||||
TableColumn column = modulesTable.getColumnModel().getColumn(i);
|
||||
if (i == 0) {
|
||||
column.setPreferredWidth(((int) (width * 0.15)));
|
||||
} else {
|
||||
column.setPreferredWidth(((int) (width * 0.84)));
|
||||
Collections.sort(modules, new Comparator<ReportModule>() {
|
||||
@Override
|
||||
public int compare(ReportModule rm1, ReportModule rm2) {
|
||||
return rm1.getName().compareTo(rm2.getName());
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
modulesJList.getSelectionModel().addListSelectionListener(this);
|
||||
modulesJList.setCellRenderer(new ModuleCellRenderer());
|
||||
modulesJList.setListData(modules.toArray());
|
||||
selectedIndex = 0;
|
||||
modulesJList.setSelectedIndex(selectedIndex);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -96,20 +92,52 @@ public final class ReportVisualPanel1 extends JPanel {
|
||||
return "Select and Configure Report Modules";
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the enabled/disabled states of all TableReportModules
|
||||
*/
|
||||
Map<TableReportModule, Boolean> getTableModuleStates() {
|
||||
return tableModuleStates;
|
||||
public ReportModule getSelectedModule() {
|
||||
return modules.get(selectedIndex);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the enabled/disabled states of all GeneralReportModules
|
||||
* Get the Selection status of the TableModules.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
Map<TableReportModule, Boolean> getTableModuleStates() {
|
||||
Map<TableReportModule, Boolean> reportModuleStates = new LinkedHashMap<>();
|
||||
ReportModule mod = getSelectedModule();
|
||||
if (tableModules.contains(mod)) {
|
||||
reportModuleStates.put((TableReportModule) mod, Boolean.TRUE);
|
||||
}
|
||||
return reportModuleStates;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the selection status of the GeneralReportModules.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
Map<GeneralReportModule, Boolean> getGeneralModuleStates() {
|
||||
return generalModuleStates;
|
||||
Map<GeneralReportModule, Boolean> reportModuleStates = new LinkedHashMap<>();
|
||||
ReportModule mod = getSelectedModule();
|
||||
if (generalModules.contains(mod)) {
|
||||
reportModuleStates.put((GeneralReportModule) mod, Boolean.TRUE);
|
||||
}
|
||||
return reportModuleStates;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get the selection status of the FileReportModules.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
Map<FileReportModule, Boolean> getFileModuleStates() {
|
||||
Map<FileReportModule, Boolean> reportModuleStates = new LinkedHashMap<>();
|
||||
ReportModule mod = getSelectedModule();
|
||||
if (fileModules.contains(mod)) {
|
||||
reportModuleStates.put((FileReportModule) mod, Boolean.TRUE);
|
||||
}
|
||||
return reportModuleStates;
|
||||
}
|
||||
|
||||
/**
|
||||
* This method is called from within the constructor to initialize the form.
|
||||
* WARNING: Do NOT modify this code. The content of this method is always
|
||||
@ -118,28 +146,15 @@ public final class ReportVisualPanel1 extends JPanel {
|
||||
// <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
|
||||
private void initComponents() {
|
||||
|
||||
modulesScrollPane = new javax.swing.JScrollPane();
|
||||
modulesTable = new javax.swing.JTable();
|
||||
reportModulesLabel = new javax.swing.JLabel();
|
||||
configurationPanel = new javax.swing.JPanel();
|
||||
descriptionScrollPane = new javax.swing.JScrollPane();
|
||||
descriptionTextPane = new javax.swing.JTextPane();
|
||||
modulesScrollPane = new javax.swing.JScrollPane();
|
||||
modulesJList = new javax.swing.JList();
|
||||
|
||||
setPreferredSize(new java.awt.Dimension(650, 250));
|
||||
|
||||
modulesTable.setBackground(new java.awt.Color(240, 240, 240));
|
||||
modulesTable.setModel(new javax.swing.table.DefaultTableModel(
|
||||
new Object [][] {
|
||||
|
||||
},
|
||||
new String [] {
|
||||
|
||||
}
|
||||
));
|
||||
modulesTable.setShowHorizontalLines(false);
|
||||
modulesTable.setShowVerticalLines(false);
|
||||
modulesScrollPane.setViewportView(modulesTable);
|
||||
|
||||
org.openide.awt.Mnemonics.setLocalizedText(reportModulesLabel, org.openide.util.NbBundle.getMessage(ReportVisualPanel1.class, "ReportVisualPanel1.reportModulesLabel.text")); // NOI18N
|
||||
|
||||
configurationPanel.setBorder(javax.swing.BorderFactory.createLineBorder(new java.awt.Color(125, 125, 125)));
|
||||
@ -152,7 +167,7 @@ public final class ReportVisualPanel1 extends JPanel {
|
||||
);
|
||||
configurationPanelLayout.setVerticalGroup(
|
||||
configurationPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
.addGap(0, 0, Short.MAX_VALUE)
|
||||
.addGap(0, 168, Short.MAX_VALUE)
|
||||
);
|
||||
|
||||
descriptionScrollPane.setBorder(null);
|
||||
@ -161,6 +176,14 @@ public final class ReportVisualPanel1 extends JPanel {
|
||||
descriptionTextPane.setBorder(null);
|
||||
descriptionScrollPane.setViewportView(descriptionTextPane);
|
||||
|
||||
modulesJList.setBackground(new java.awt.Color(240, 240, 240));
|
||||
modulesJList.setModel(new javax.swing.AbstractListModel() {
|
||||
String[] strings = { "Item 1", "Item 2", "Item 3", "Item 4", "Item 5" };
|
||||
public int getSize() { return strings.length; }
|
||||
public Object getElementAt(int i) { return strings[i]; }
|
||||
});
|
||||
modulesScrollPane.setViewportView(modulesJList);
|
||||
|
||||
javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
|
||||
this.setLayout(layout);
|
||||
layout.setHorizontalGroup(
|
||||
@ -169,8 +192,8 @@ public final class ReportVisualPanel1 extends JPanel {
|
||||
.addContainerGap()
|
||||
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
.addComponent(reportModulesLabel)
|
||||
.addComponent(modulesScrollPane, javax.swing.GroupLayout.PREFERRED_SIZE, 186, javax.swing.GroupLayout.PREFERRED_SIZE))
|
||||
.addGap(10, 10, 10)
|
||||
.addComponent(modulesScrollPane, javax.swing.GroupLayout.PREFERRED_SIZE, 190, javax.swing.GroupLayout.PREFERRED_SIZE))
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
.addComponent(configurationPanel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
|
||||
.addComponent(descriptionScrollPane))
|
||||
@ -183,11 +206,11 @@ public final class ReportVisualPanel1 extends JPanel {
|
||||
.addComponent(reportModulesLabel)
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
.addComponent(modulesScrollPane, javax.swing.GroupLayout.DEFAULT_SIZE, 208, Short.MAX_VALUE)
|
||||
.addGroup(layout.createSequentialGroup()
|
||||
.addComponent(configurationPanel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||
.addComponent(descriptionScrollPane, javax.swing.GroupLayout.PREFERRED_SIZE, 32, javax.swing.GroupLayout.PREFERRED_SIZE)))
|
||||
.addComponent(descriptionScrollPane, javax.swing.GroupLayout.PREFERRED_SIZE, 32, javax.swing.GroupLayout.PREFERRED_SIZE))
|
||||
.addComponent(modulesScrollPane))
|
||||
.addContainerGap())
|
||||
);
|
||||
}// </editor-fold>//GEN-END:initComponents
|
||||
@ -195,104 +218,47 @@ public final class ReportVisualPanel1 extends JPanel {
|
||||
private javax.swing.JPanel configurationPanel;
|
||||
private javax.swing.JScrollPane descriptionScrollPane;
|
||||
private javax.swing.JTextPane descriptionTextPane;
|
||||
private javax.swing.JList modulesJList;
|
||||
private javax.swing.JScrollPane modulesScrollPane;
|
||||
private javax.swing.JTable modulesTable;
|
||||
private javax.swing.JLabel reportModulesLabel;
|
||||
// End of variables declaration//GEN-END:variables
|
||||
|
||||
@Override
|
||||
public void valueChanged(ListSelectionEvent e) {
|
||||
if (e.getValueIsAdjusting()) {
|
||||
return;
|
||||
}
|
||||
configurationPanel.removeAll();
|
||||
ListSelectionModel m = (ListSelectionModel) e.getSource();
|
||||
// single selection, so max selection index is the only one selected.
|
||||
selectedIndex = m.getMaxSelectionIndex();
|
||||
|
||||
private class ModulesTableModel extends AbstractTableModel {
|
||||
|
||||
@Override
|
||||
public int getRowCount() {
|
||||
return tableModules.size() + generalModules.size();
|
||||
JPanel panel = new DefaultReportConfigurationPanel();
|
||||
ReportModule module = modules.get(selectedIndex);
|
||||
boolean generalModuleSelected = false;
|
||||
if (module instanceof GeneralReportModule) {
|
||||
JPanel generalPanel = ((GeneralReportModule) module).getConfigurationPanel();
|
||||
panel = (generalPanel == null) ? new JPanel() : panel;
|
||||
generalModuleSelected = true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getColumnCount() {
|
||||
return 2;
|
||||
}
|
||||
descriptionTextPane.setText(module.getDescription());
|
||||
configurationPanel.add(panel, BorderLayout.CENTER);
|
||||
configurationPanel.revalidate();
|
||||
|
||||
@Override
|
||||
public Object getValueAt(int rowIndex, int columnIndex) {
|
||||
ReportModule module;
|
||||
if (rowIndex < tableModules.size()) {
|
||||
module = tableModules.get(rowIndex);
|
||||
} else {
|
||||
module = generalModules.get(rowIndex - tableModules.size());
|
||||
}
|
||||
if (columnIndex == 0 && rowIndex < tableModules.size()) {
|
||||
return tableModuleStates.get(tableModules.get(rowIndex));
|
||||
} else if (columnIndex == 0 && rowIndex >= tableModules.size()) {
|
||||
return generalModuleStates.get(generalModules.get(rowIndex - tableModules.size()));
|
||||
} else {
|
||||
return module.getName();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isCellEditable(int rowIndex, int columnIndex) {
|
||||
return columnIndex == 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setValueAt(Object aValue, int rowIndex, int columnIndex) {
|
||||
if (columnIndex == 0 && rowIndex < tableModules.size()) {
|
||||
tableModuleStates.put(tableModules.get(rowIndex), (Boolean) aValue);
|
||||
} else if (columnIndex == 0 && rowIndex >= tableModules.size()) {
|
||||
generalModuleStates.put(generalModules.get(rowIndex - tableModules.size()), (Boolean) aValue);
|
||||
}
|
||||
// Check if there are any TableReportModules enabled
|
||||
boolean tableModuleEnabled = false;
|
||||
for (Entry<TableReportModule, Boolean> module : tableModuleStates.entrySet()) {
|
||||
if (module.getValue()) {
|
||||
tableModuleEnabled = true;
|
||||
}
|
||||
}
|
||||
boolean generalModuleEnabled = false;
|
||||
for (Entry<GeneralReportModule, Boolean> module : generalModuleStates.entrySet()) {
|
||||
if (module.getValue()) {
|
||||
generalModuleEnabled = true;
|
||||
}
|
||||
}
|
||||
if(tableModuleEnabled) {
|
||||
wizPanel.setNext(true);
|
||||
wizPanel.setFinish(false);
|
||||
} else if(generalModuleEnabled) {
|
||||
wizPanel.setFinish(true);
|
||||
wizPanel.setNext(false);
|
||||
} else {
|
||||
wizPanel.setFinish(false);
|
||||
wizPanel.setNext(false);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<?> getColumnClass(int c) {
|
||||
return getValueAt(0, c).getClass();
|
||||
}
|
||||
wizPanel.setNext(!generalModuleSelected);
|
||||
wizPanel.setFinish(generalModuleSelected);
|
||||
}
|
||||
|
||||
private class ModuleSelectionListener implements ListSelectionListener {
|
||||
|
||||
private class ModuleCellRenderer extends JRadioButton implements ListCellRenderer<ReportModule> {
|
||||
|
||||
@Override
|
||||
public void valueChanged(ListSelectionEvent e) {
|
||||
configurationPanel.removeAll();
|
||||
int rowIndex = modulesTable.getSelectedRow();
|
||||
if (rowIndex < tableModules.size()) {
|
||||
configurationPanel.add(new DefaultReportConfigurationPanel(), BorderLayout.CENTER);
|
||||
descriptionTextPane.setText(tableModules.get(rowIndex).getDescription());
|
||||
} else {
|
||||
GeneralReportModule module = generalModules.get(rowIndex - tableModules.size());
|
||||
JPanel panel = module.getConfigurationPanel();
|
||||
descriptionTextPane.setText(module.getDescription());
|
||||
if (panel != null) {
|
||||
configurationPanel.add(panel, BorderLayout.CENTER);
|
||||
}
|
||||
}
|
||||
configurationPanel.revalidate();
|
||||
configurationPanel.repaint();
|
||||
public Component getListCellRendererComponent(JList list, ReportModule value, int index, boolean isSelected, boolean cellHasFocus) {
|
||||
this.setText(value.getName());
|
||||
this.setEnabled(true);
|
||||
this.setSelected(isSelected);
|
||||
return this;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -29,23 +29,23 @@
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<Group type="102" attributes="0">
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<Component id="taggedResultsRadioButton" alignment="0" min="-2" max="-2" attributes="0"/>
|
||||
<Component id="allResultsRadioButton" alignment="0" min="-2" max="-2" attributes="0"/>
|
||||
<Component id="dataLabel" alignment="0" min="-2" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
<EmptySpace min="0" pref="481" max="32767" attributes="0"/>
|
||||
</Group>
|
||||
<Group type="102" alignment="1" attributes="0">
|
||||
<EmptySpace min="-2" pref="21" max="-2" attributes="0"/>
|
||||
<Component id="tagsScrollPane" max="32767" attributes="0"/>
|
||||
<EmptySpace type="unrelated" max="-2" attributes="0"/>
|
||||
<Group type="103" groupAlignment="0" max="-2" attributes="0">
|
||||
<Component id="advancedButton" alignment="1" max="32767" attributes="0"/>
|
||||
<Component id="advancedButton" alignment="1" pref="89" max="32767" attributes="0"/>
|
||||
<Component id="deselectAllButton" max="32767" attributes="0"/>
|
||||
<Component id="selectAllButton" max="32767" attributes="0"/>
|
||||
</Group>
|
||||
</Group>
|
||||
<Group type="102" attributes="0">
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<Component id="taggedResultsRadioButton" alignment="0" min="-2" max="-2" attributes="0"/>
|
||||
<Component id="dataLabel" alignment="0" min="-2" max="-2" attributes="0"/>
|
||||
<Component id="allResultsRadioButton" alignment="0" min="-2" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
<EmptySpace min="0" pref="481" max="32767" attributes="0"/>
|
||||
</Group>
|
||||
</Group>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
</Group>
|
||||
|
@ -122,7 +122,7 @@ public final class ReportVisualPanel2 extends JPanel {
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return "Configure HTML and Excel reports";
|
||||
return "Configure Artifact Reports";
|
||||
}
|
||||
|
||||
/**
|
||||
@ -240,19 +240,19 @@ public final class ReportVisualPanel2 extends JPanel {
|
||||
.addContainerGap()
|
||||
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
.addGroup(layout.createSequentialGroup()
|
||||
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
.addComponent(taggedResultsRadioButton)
|
||||
.addComponent(allResultsRadioButton)
|
||||
.addComponent(dataLabel))
|
||||
.addGap(0, 481, Short.MAX_VALUE))
|
||||
.addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
|
||||
.addGap(21, 21, 21)
|
||||
.addComponent(tagsScrollPane)
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
|
||||
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false)
|
||||
.addComponent(advancedButton, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
|
||||
.addComponent(advancedButton, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.DEFAULT_SIZE, 89, Short.MAX_VALUE)
|
||||
.addComponent(deselectAllButton, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
|
||||
.addComponent(selectAllButton, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))))
|
||||
.addComponent(selectAllButton, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)))
|
||||
.addGroup(layout.createSequentialGroup()
|
||||
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
.addComponent(taggedResultsRadioButton)
|
||||
.addComponent(dataLabel)
|
||||
.addComponent(allResultsRadioButton))
|
||||
.addGap(0, 481, Short.MAX_VALUE)))
|
||||
.addContainerGap())
|
||||
);
|
||||
layout.setVerticalGroup(
|
||||
|
@ -66,10 +66,13 @@ public final class ReportWizardAction extends CallableSystemAction implements P
|
||||
public static void doReportWizard() {
|
||||
WizardDescriptor wiz = new WizardDescriptor(new ReportWizardIterator());
|
||||
wiz.setTitleFormat(new MessageFormat("{0} {1}"));
|
||||
wiz.setTitle("Generate Report");
|
||||
wiz.setTitle("Generate Report");
|
||||
if (DialogDisplayer.getDefault().notify(wiz) == WizardDescriptor.FINISH_OPTION) {
|
||||
ReportGenerator generator = new ReportGenerator((Map<TableReportModule, Boolean>)wiz.getProperty("tableModuleStates"), (Map<GeneralReportModule, Boolean>)wiz.getProperty("generalModuleStates"));
|
||||
ReportGenerator generator = new ReportGenerator((Map<TableReportModule, Boolean>)wiz.getProperty("tableModuleStates"),
|
||||
(Map<GeneralReportModule, Boolean>)wiz.getProperty("generalModuleStates"),
|
||||
(Map<FileReportModule, Boolean>)wiz.getProperty("fileModuleStates"));
|
||||
generator.generateArtifactTableReports((Map<ARTIFACT_TYPE, Boolean>)wiz.getProperty("artifactStates"), (Map<String, Boolean>)wiz.getProperty("tagStates"));
|
||||
generator.generateFileListReports((Map<FileReportDataTypes, Boolean>)wiz.getProperty("fileReportOptions"));
|
||||
generator.generateGeneralReports();
|
||||
generator.displayProgressPanels();
|
||||
}
|
||||
|
96
Core/src/org/sleuthkit/autopsy/report/ReportWizardFileOptionsPanel.java
Executable file
96
Core/src/org/sleuthkit/autopsy/report/ReportWizardFileOptionsPanel.java
Executable file
@ -0,0 +1,96 @@
|
||||
/*
|
||||
* Autopsy Forensic Browser
|
||||
*
|
||||
* Copyright 2013 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.report;
|
||||
|
||||
import java.awt.event.ActionEvent;
|
||||
import java.awt.event.ActionListener;
|
||||
import javax.swing.JButton;
|
||||
import javax.swing.event.ChangeListener;
|
||||
import org.openide.WizardDescriptor;
|
||||
import org.openide.util.HelpCtx;
|
||||
|
||||
/**
|
||||
* Wizard panel that allows configuration of File Report options.
|
||||
*
|
||||
* @author jwallace
|
||||
*/
|
||||
public class ReportWizardFileOptionsPanel implements WizardDescriptor.FinishablePanel<WizardDescriptor>{
|
||||
private WizardDescriptor wiz;
|
||||
private ReportWizardFileOptionsVisualPanel component;
|
||||
private JButton finishButton;
|
||||
|
||||
ReportWizardFileOptionsPanel() {
|
||||
finishButton = new JButton("Finish");
|
||||
finishButton.setEnabled(false);
|
||||
|
||||
finishButton.addActionListener(new ActionListener() {
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
wiz.doFinishClick();
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
public void setFinish(boolean enable) {
|
||||
finishButton.setEnabled(enable);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isFinishPanel() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ReportWizardFileOptionsVisualPanel getComponent() {
|
||||
if (component == null) {
|
||||
component = new ReportWizardFileOptionsVisualPanel(this);
|
||||
}
|
||||
return component;
|
||||
}
|
||||
|
||||
@Override
|
||||
public HelpCtx getHelp() {
|
||||
return HelpCtx.DEFAULT_HELP;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void readSettings(WizardDescriptor data) {
|
||||
this.wiz = data;
|
||||
wiz.setOptions(new Object[] {WizardDescriptor.PREVIOUS_OPTION, WizardDescriptor.NEXT_OPTION, finishButton, WizardDescriptor.CANCEL_OPTION});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void storeSettings(WizardDescriptor data) {
|
||||
data.putProperty("fileReportOptions", getComponent().getFileReportOptions());
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isValid() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addChangeListener(ChangeListener cl) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeChangeListener(ChangeListener cl) {
|
||||
}
|
||||
|
||||
}
|
107
Core/src/org/sleuthkit/autopsy/report/ReportWizardFileOptionsVisualPanel.form
Executable file
107
Core/src/org/sleuthkit/autopsy/report/ReportWizardFileOptionsVisualPanel.form
Executable file
@ -0,0 +1,107 @@
|
||||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
|
||||
<Form version="1.5" maxVersion="1.8" type="org.netbeans.modules.form.forminfo.JPanelFormInfo">
|
||||
<AuxValues>
|
||||
<AuxValue name="FormSettings_autoResourcing" type="java.lang.Integer" value="1"/>
|
||||
<AuxValue name="FormSettings_autoSetComponentName" type="java.lang.Boolean" value="false"/>
|
||||
<AuxValue name="FormSettings_generateFQN" type="java.lang.Boolean" value="true"/>
|
||||
<AuxValue name="FormSettings_generateMnemonicsCode" type="java.lang.Boolean" value="true"/>
|
||||
<AuxValue name="FormSettings_i18nAutoMode" type="java.lang.Boolean" value="true"/>
|
||||
<AuxValue name="FormSettings_layoutCodeTarget" type="java.lang.Integer" value="1"/>
|
||||
<AuxValue name="FormSettings_listenerGenerationStyle" type="java.lang.Integer" value="0"/>
|
||||
<AuxValue name="FormSettings_variablesLocal" type="java.lang.Boolean" value="false"/>
|
||||
<AuxValue name="FormSettings_variablesModifier" type="java.lang.Integer" value="2"/>
|
||||
</AuxValues>
|
||||
|
||||
<Layout>
|
||||
<DimensionLayout dim="0">
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<Group type="102" alignment="0" attributes="0">
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<Component id="jScrollPane1" max="32767" attributes="0"/>
|
||||
<Group type="102" attributes="0">
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<Component id="jLabel1" min="-2" max="-2" attributes="0"/>
|
||||
<Group type="102" alignment="0" attributes="0">
|
||||
<Component id="selectAllButton" min="-2" pref="87" max="-2" attributes="0"/>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Component id="deselectAllButton" min="-2" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
</Group>
|
||||
<EmptySpace min="0" pref="210" max="32767" attributes="0"/>
|
||||
</Group>
|
||||
</Group>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
</Group>
|
||||
</Group>
|
||||
</DimensionLayout>
|
||||
<DimensionLayout dim="1">
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<Group type="102" alignment="0" attributes="0">
|
||||
<EmptySpace min="-2" pref="10" max="-2" attributes="0"/>
|
||||
<Component id="jLabel1" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace type="unrelated" max="-2" attributes="0"/>
|
||||
<Component id="jScrollPane1" pref="220" max="32767" attributes="0"/>
|
||||
<EmptySpace type="unrelated" max="-2" attributes="0"/>
|
||||
<Group type="103" groupAlignment="3" attributes="0">
|
||||
<Component id="deselectAllButton" alignment="3" min="-2" max="-2" attributes="0"/>
|
||||
<Component id="selectAllButton" alignment="3" min="-2" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
</Group>
|
||||
</Group>
|
||||
</DimensionLayout>
|
||||
</Layout>
|
||||
<SubComponents>
|
||||
<Container class="javax.swing.JScrollPane" name="jScrollPane1">
|
||||
<AuxValues>
|
||||
<AuxValue name="autoScrollPane" type="java.lang.Boolean" value="true"/>
|
||||
</AuxValues>
|
||||
|
||||
<Layout class="org.netbeans.modules.form.compat2.layouts.support.JScrollPaneSupportLayout"/>
|
||||
<SubComponents>
|
||||
<Component class="javax.swing.JList" name="optionsList">
|
||||
<Properties>
|
||||
<Property name="model" type="javax.swing.ListModel" editor="org.netbeans.modules.form.editors2.ListModelEditor">
|
||||
<StringArray count="5">
|
||||
<StringItem index="0" value="Item 1"/>
|
||||
<StringItem index="1" value="Item 2"/>
|
||||
<StringItem index="2" value="Item 3"/>
|
||||
<StringItem index="3" value="Item 4"/>
|
||||
<StringItem index="4" value="Item 5"/>
|
||||
</StringArray>
|
||||
</Property>
|
||||
</Properties>
|
||||
</Component>
|
||||
</SubComponents>
|
||||
</Container>
|
||||
<Component class="javax.swing.JButton" name="selectAllButton">
|
||||
<Properties>
|
||||
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/report/Bundle.properties" key="ReportWizardFileOptionsVisualPanel.selectAllButton.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
<Events>
|
||||
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="selectAllButtonActionPerformed"/>
|
||||
</Events>
|
||||
</Component>
|
||||
<Component class="javax.swing.JButton" name="deselectAllButton">
|
||||
<Properties>
|
||||
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/report/Bundle.properties" key="ReportWizardFileOptionsVisualPanel.deselectAllButton.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
<Events>
|
||||
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="deselectAllButtonActionPerformed"/>
|
||||
</Events>
|
||||
</Component>
|
||||
<Component class="javax.swing.JLabel" name="jLabel1">
|
||||
<Properties>
|
||||
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/report/Bundle.properties" key="ReportWizardFileOptionsVisualPanel.jLabel1.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
</Component>
|
||||
</SubComponents>
|
||||
</Form>
|
267
Core/src/org/sleuthkit/autopsy/report/ReportWizardFileOptionsVisualPanel.java
Executable file
267
Core/src/org/sleuthkit/autopsy/report/ReportWizardFileOptionsVisualPanel.java
Executable file
@ -0,0 +1,267 @@
|
||||
/*
|
||||
* Autopsy Forensic Browser
|
||||
*
|
||||
* Copyright 2013 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.report;
|
||||
|
||||
import java.awt.Component;
|
||||
import java.awt.event.MouseAdapter;
|
||||
import java.awt.event.MouseEvent;
|
||||
import java.util.Arrays;
|
||||
import java.util.EnumMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import javax.swing.JCheckBox;
|
||||
import javax.swing.JLabel;
|
||||
import javax.swing.JList;
|
||||
import javax.swing.ListCellRenderer;
|
||||
import javax.swing.ListModel;
|
||||
import javax.swing.event.ListDataListener;
|
||||
|
||||
/**
|
||||
* Visual component of the File Report Configuration panel of the Report Wizard.
|
||||
*
|
||||
* @author jwallace
|
||||
*/
|
||||
public class ReportWizardFileOptionsVisualPanel extends javax.swing.JPanel {
|
||||
private List<FileReportDataTypes> options;
|
||||
private Map<FileReportDataTypes, Boolean> optionStates = new EnumMap<>(FileReportDataTypes.class);
|
||||
private ListModel model;
|
||||
private ReportWizardFileOptionsPanel wizPanel;
|
||||
|
||||
|
||||
public ReportWizardFileOptionsVisualPanel(ReportWizardFileOptionsPanel wizPanel) {
|
||||
this.wizPanel = wizPanel;
|
||||
initComponents();
|
||||
initOptionsList();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return "Configure File Report";
|
||||
}
|
||||
|
||||
/**
|
||||
* Populate the list of File Report Information that can be selected.
|
||||
*/
|
||||
private void initOptionsList() {
|
||||
options = Arrays.asList(FileReportDataTypes.values());
|
||||
for(FileReportDataTypes col : options) {
|
||||
optionStates.put(col, Boolean.FALSE);
|
||||
}
|
||||
|
||||
model = new OptionsListModel();
|
||||
optionsList.setModel(model);
|
||||
optionsList.setCellRenderer(new OptionsListRenderer());
|
||||
optionsList.setVisibleRowCount(-1);
|
||||
|
||||
selectAllButton.setEnabled(true);
|
||||
deselectAllButton.setEnabled(false);
|
||||
|
||||
// Add the ability to enable and disable Tag checkboxes to the list
|
||||
optionsList.addMouseListener(new MouseAdapter() {
|
||||
@Override
|
||||
public void mousePressed(MouseEvent evt) {
|
||||
JList list = (JList) evt.getSource();
|
||||
int index = list.locationToIndex(evt.getPoint());
|
||||
FileReportDataTypes value = (FileReportDataTypes) model.getElementAt(index);
|
||||
optionStates.put(value, !optionStates.get(value));
|
||||
list.repaint();
|
||||
boolean anySelected = anySelected();
|
||||
deselectAllButton.setEnabled(anySelected);
|
||||
wizPanel.setFinish(anySelected);
|
||||
selectAllButton.setEnabled(notAllSelected());
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Are any options selected?
|
||||
* @return
|
||||
*/
|
||||
private boolean anySelected() {
|
||||
for (Boolean b : optionStates.values()) {
|
||||
if (b) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Are no options selected?
|
||||
* @return
|
||||
*/
|
||||
private boolean notAllSelected() {
|
||||
for (Boolean b : optionStates.values()) {
|
||||
if (!b) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the user-selected settings.
|
||||
* @return
|
||||
*/
|
||||
Map<FileReportDataTypes, Boolean> getFileReportOptions() {
|
||||
return optionStates;
|
||||
}
|
||||
/**
|
||||
* This method is called from within the constructor to initialize the form.
|
||||
* WARNING: Do NOT modify this code. The content of this method is always
|
||||
* regenerated by the Form Editor.
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
// <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
|
||||
private void initComponents() {
|
||||
|
||||
jScrollPane1 = new javax.swing.JScrollPane();
|
||||
optionsList = new javax.swing.JList();
|
||||
selectAllButton = new javax.swing.JButton();
|
||||
deselectAllButton = new javax.swing.JButton();
|
||||
jLabel1 = new javax.swing.JLabel();
|
||||
|
||||
optionsList.setModel(new javax.swing.AbstractListModel() {
|
||||
String[] strings = { "Item 1", "Item 2", "Item 3", "Item 4", "Item 5" };
|
||||
public int getSize() { return strings.length; }
|
||||
public Object getElementAt(int i) { return strings[i]; }
|
||||
});
|
||||
jScrollPane1.setViewportView(optionsList);
|
||||
|
||||
org.openide.awt.Mnemonics.setLocalizedText(selectAllButton, org.openide.util.NbBundle.getMessage(ReportWizardFileOptionsVisualPanel.class, "ReportWizardFileOptionsVisualPanel.selectAllButton.text")); // NOI18N
|
||||
selectAllButton.addActionListener(new java.awt.event.ActionListener() {
|
||||
public void actionPerformed(java.awt.event.ActionEvent evt) {
|
||||
selectAllButtonActionPerformed(evt);
|
||||
}
|
||||
});
|
||||
|
||||
org.openide.awt.Mnemonics.setLocalizedText(deselectAllButton, org.openide.util.NbBundle.getMessage(ReportWizardFileOptionsVisualPanel.class, "ReportWizardFileOptionsVisualPanel.deselectAllButton.text")); // NOI18N
|
||||
deselectAllButton.addActionListener(new java.awt.event.ActionListener() {
|
||||
public void actionPerformed(java.awt.event.ActionEvent evt) {
|
||||
deselectAllButtonActionPerformed(evt);
|
||||
}
|
||||
});
|
||||
|
||||
org.openide.awt.Mnemonics.setLocalizedText(jLabel1, org.openide.util.NbBundle.getMessage(ReportWizardFileOptionsVisualPanel.class, "ReportWizardFileOptionsVisualPanel.jLabel1.text")); // NOI18N
|
||||
|
||||
javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
|
||||
this.setLayout(layout);
|
||||
layout.setHorizontalGroup(
|
||||
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
.addGroup(layout.createSequentialGroup()
|
||||
.addContainerGap()
|
||||
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
.addComponent(jScrollPane1)
|
||||
.addGroup(layout.createSequentialGroup()
|
||||
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
.addComponent(jLabel1)
|
||||
.addGroup(layout.createSequentialGroup()
|
||||
.addComponent(selectAllButton, javax.swing.GroupLayout.PREFERRED_SIZE, 87, javax.swing.GroupLayout.PREFERRED_SIZE)
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||
.addComponent(deselectAllButton)))
|
||||
.addGap(0, 210, Short.MAX_VALUE)))
|
||||
.addContainerGap())
|
||||
);
|
||||
layout.setVerticalGroup(
|
||||
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
.addGroup(layout.createSequentialGroup()
|
||||
.addGap(10, 10, 10)
|
||||
.addComponent(jLabel1)
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
|
||||
.addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 220, Short.MAX_VALUE)
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
|
||||
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
|
||||
.addComponent(deselectAllButton)
|
||||
.addComponent(selectAllButton))
|
||||
.addContainerGap())
|
||||
);
|
||||
}// </editor-fold>//GEN-END:initComponents
|
||||
|
||||
private void selectAllButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_selectAllButtonActionPerformed
|
||||
for (FileReportDataTypes option : options) {
|
||||
optionStates.put(option, Boolean.TRUE);
|
||||
}
|
||||
optionsList.repaint();
|
||||
selectAllButton.setEnabled(false);
|
||||
deselectAllButton.setEnabled(true);
|
||||
wizPanel.setFinish(true);
|
||||
}//GEN-LAST:event_selectAllButtonActionPerformed
|
||||
|
||||
private void deselectAllButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_deselectAllButtonActionPerformed
|
||||
for (FileReportDataTypes option : options) {
|
||||
optionStates.put(option, Boolean.FALSE);
|
||||
}
|
||||
optionsList.repaint();
|
||||
selectAllButton.setEnabled(true);
|
||||
deselectAllButton.setEnabled(false);
|
||||
wizPanel.setFinish(false);
|
||||
}//GEN-LAST:event_deselectAllButtonActionPerformed
|
||||
|
||||
// Variables declaration - do not modify//GEN-BEGIN:variables
|
||||
private javax.swing.JButton deselectAllButton;
|
||||
private javax.swing.JLabel jLabel1;
|
||||
private javax.swing.JScrollPane jScrollPane1;
|
||||
private javax.swing.JList optionsList;
|
||||
private javax.swing.JButton selectAllButton;
|
||||
// End of variables declaration//GEN-END:variables
|
||||
|
||||
private class OptionsListModel implements ListModel {
|
||||
|
||||
@Override
|
||||
public int getSize() {
|
||||
return options.size();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getElementAt(int index) {
|
||||
return options.get(index);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addListDataListener(ListDataListener l) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeListDataListener(ListDataListener l) {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Render each item in the list to be a selectable check box.
|
||||
*/
|
||||
private class OptionsListRenderer extends JCheckBox implements ListCellRenderer {
|
||||
|
||||
@Override
|
||||
public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) {
|
||||
if (value != null) {
|
||||
FileReportDataTypes col = (FileReportDataTypes) value;
|
||||
setEnabled(list.isEnabled());
|
||||
setSelected(optionStates.get(col));
|
||||
setFont(list.getFont());
|
||||
setBackground(list.getBackground());
|
||||
setForeground(list.getForeground());
|
||||
setText(col.getName());
|
||||
return this;
|
||||
}
|
||||
return new JLabel();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
@ -19,22 +19,49 @@
|
||||
package org.sleuthkit.autopsy.report;
|
||||
|
||||
import java.awt.Component;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.NoSuchElementException;
|
||||
import javax.swing.JComponent;
|
||||
import javax.swing.event.ChangeListener;
|
||||
import org.openide.WizardDescriptor;
|
||||
import org.openide.util.NbPreferences;
|
||||
|
||||
public final class ReportWizardIterator implements WizardDescriptor.Iterator<WizardDescriptor> {
|
||||
private int index;
|
||||
|
||||
private ReportWizardPanel1 firstPanel;
|
||||
private ReportWizardPanel2 tableConfigPanel;
|
||||
private ReportWizardFileOptionsPanel fileConfigPanel;
|
||||
|
||||
private List<WizardDescriptor.Panel<WizardDescriptor>> panels;
|
||||
|
||||
// Panels that should be shown if both Table and File report modules should
|
||||
// be configured.
|
||||
private WizardDescriptor.Panel<WizardDescriptor>[] allConfigPanels;
|
||||
private String[] allConfigIndex;
|
||||
// Panels that should be shown if only Table report modules should
|
||||
// be configured.
|
||||
private WizardDescriptor.Panel<WizardDescriptor>[] tableConfigPanels;
|
||||
private String[] tableConfigIndex;
|
||||
// Panels that should be shown if only File report modules should
|
||||
// be configured.
|
||||
private WizardDescriptor.Panel<WizardDescriptor>[] fileConfigPanels;
|
||||
private String[] fileConfigIndex;
|
||||
|
||||
ReportWizardIterator() {
|
||||
firstPanel = new ReportWizardPanel1();
|
||||
tableConfigPanel = new ReportWizardPanel2();
|
||||
fileConfigPanel = new ReportWizardFileOptionsPanel();
|
||||
|
||||
allConfigPanels = new WizardDescriptor.Panel[]{firstPanel, tableConfigPanel, fileConfigPanel};
|
||||
tableConfigPanels = new WizardDescriptor.Panel[]{firstPanel, tableConfigPanel};
|
||||
fileConfigPanels = new WizardDescriptor.Panel[]{firstPanel, fileConfigPanel};
|
||||
}
|
||||
|
||||
private List<WizardDescriptor.Panel<WizardDescriptor>> getPanels() {
|
||||
if (panels == null) {
|
||||
panels = new ArrayList<WizardDescriptor.Panel<WizardDescriptor>>();
|
||||
panels.add(new ReportWizardPanel1());
|
||||
panels.add(new ReportWizardPanel2());
|
||||
panels = Arrays.asList(allConfigPanels);
|
||||
String[] steps = new String[panels.size()];
|
||||
for (int i = 0; i < panels.size(); i++) {
|
||||
Component c = panels.get(i).getComponent();
|
||||
@ -49,9 +76,32 @@ public final class ReportWizardIterator implements WizardDescriptor.Iterator<Wiz
|
||||
jc.putClientProperty(WizardDescriptor.PROP_CONTENT_NUMBERED, true);
|
||||
}
|
||||
}
|
||||
|
||||
allConfigIndex = steps;
|
||||
tableConfigIndex = new String[] {steps[0], steps[1]};
|
||||
fileConfigIndex = new String[] {steps[0], steps[2]};
|
||||
}
|
||||
return panels;
|
||||
}
|
||||
|
||||
/**
|
||||
* Change which panels will be shown based on the selection of reporting modules.
|
||||
* @param moreConfig true if a GeneralReportModule was selected
|
||||
* @param tableConfig true if a TReportModule was selected
|
||||
*/
|
||||
private void enableConfigPanels(boolean generalModule, boolean tableModule) {
|
||||
if (generalModule) {
|
||||
// General Module selected, no additional panels
|
||||
} else if (tableModule) {
|
||||
// Table Module selected, need Artifact Configuration Panel
|
||||
// (ReportWizardPanel2)
|
||||
panels = Arrays.asList(tableConfigPanels);
|
||||
} else {
|
||||
// File Module selected, need File Report Configuration Panel
|
||||
// (ReportWizardFileOptionsPanel)
|
||||
panels = Arrays.asList(fileConfigPanels);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public WizardDescriptor.Panel<WizardDescriptor> current() {
|
||||
@ -78,6 +128,16 @@ public final class ReportWizardIterator implements WizardDescriptor.Iterator<Wiz
|
||||
if (!hasNext()) {
|
||||
throw new NoSuchElementException();
|
||||
}
|
||||
|
||||
if(index == 0) {
|
||||
// Update path through configuration panels
|
||||
boolean generalModule, tableModule;
|
||||
// These preferences are set in ReportWizardPanel1.storeSettings()
|
||||
generalModule = NbPreferences.forModule(ReportWizardPanel1.class).getBoolean("generalModule", true);
|
||||
tableModule = NbPreferences.forModule(ReportWizardPanel1.class).getBoolean("tableModule", true);
|
||||
enableConfigPanels(generalModule, tableModule);
|
||||
}
|
||||
|
||||
index++;
|
||||
}
|
||||
|
||||
|
@ -20,10 +20,14 @@ package org.sleuthkit.autopsy.report;
|
||||
|
||||
import java.awt.event.ActionEvent;
|
||||
import java.awt.event.ActionListener;
|
||||
import java.util.Collection;
|
||||
import java.util.Map;
|
||||
import java.util.prefs.Preferences;
|
||||
import javax.swing.JButton;
|
||||
import javax.swing.event.ChangeListener;
|
||||
import org.openide.WizardDescriptor;
|
||||
import org.openide.util.HelpCtx;
|
||||
import org.openide.util.NbPreferences;
|
||||
|
||||
public class ReportWizardPanel1 implements WizardDescriptor.FinishablePanel<WizardDescriptor> {
|
||||
private WizardDescriptor wiz;
|
||||
@ -102,7 +106,30 @@ public class ReportWizardPanel1 implements WizardDescriptor.FinishablePanel<Wiza
|
||||
|
||||
@Override
|
||||
public void storeSettings(WizardDescriptor wiz) {
|
||||
wiz.putProperty("tableModuleStates", getComponent().getTableModuleStates());
|
||||
wiz.putProperty("generalModuleStates", getComponent().getGeneralModuleStates());
|
||||
Map<TableReportModule, Boolean> tables = getComponent().getTableModuleStates();
|
||||
Map<GeneralReportModule, Boolean> generals = getComponent().getGeneralModuleStates();
|
||||
wiz.putProperty("tableModuleStates", tables);
|
||||
wiz.putProperty("generalModuleStates", generals);
|
||||
wiz.putProperty("fileModuleStates", getComponent().getFileModuleStates());
|
||||
|
||||
// Store preferences that WizardIterator will use to determine what
|
||||
// panels need to be shown
|
||||
Preferences prefs = NbPreferences.forModule(ReportWizardPanel1.class);
|
||||
prefs.putBoolean("tableModule", any(tables.values()));
|
||||
prefs.putBoolean("generalModule", any(generals.values()));
|
||||
}
|
||||
|
||||
/**
|
||||
* Are any of the given booleans true?
|
||||
* @param bools
|
||||
* @return
|
||||
*/
|
||||
private boolean any(Collection<Boolean> bools) {
|
||||
for (Boolean b : bools) {
|
||||
if (b) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
@ -24,15 +24,26 @@ import javax.swing.JButton;
|
||||
import javax.swing.event.ChangeListener;
|
||||
import org.openide.WizardDescriptor;
|
||||
import org.openide.util.HelpCtx;
|
||||
import org.openide.util.NbPreferences;
|
||||
|
||||
public class ReportWizardPanel2 implements WizardDescriptor.Panel<WizardDescriptor> {
|
||||
private ReportVisualPanel2 component;
|
||||
private JButton finishButton;
|
||||
private JButton nextButton;
|
||||
private WizardDescriptor wiz;
|
||||
|
||||
ReportWizardPanel2() {
|
||||
finishButton = new JButton("Finish");
|
||||
finishButton.setEnabled(true);
|
||||
|
||||
nextButton = new JButton("Next >");
|
||||
nextButton.setEnabled(true);
|
||||
|
||||
nextButton.addActionListener(new ActionListener() {
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
wiz.doNextClick();
|
||||
}
|
||||
});
|
||||
|
||||
finishButton.addActionListener(new ActionListener() {
|
||||
@Override
|
||||
@ -69,14 +80,16 @@ public class ReportWizardPanel2 implements WizardDescriptor.Panel<WizardDescript
|
||||
}
|
||||
|
||||
public void setFinish(boolean enabled) {
|
||||
nextButton.setEnabled(false);
|
||||
finishButton.setEnabled(enabled);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void readSettings(WizardDescriptor wiz) {
|
||||
// Re-enable the normal wizard buttons
|
||||
setFinish(true);
|
||||
this.wiz = wiz;
|
||||
wiz.setOptions(new Object[] {WizardDescriptor.PREVIOUS_OPTION, WizardDescriptor.NEXT_OPTION, finishButton, WizardDescriptor.CANCEL_OPTION});
|
||||
wiz.setOptions(new Object[] {WizardDescriptor.PREVIOUS_OPTION, nextButton, finishButton, WizardDescriptor.CANCEL_OPTION});
|
||||
}
|
||||
|
||||
@Override
|
||||
|
4
NEWS.txt
4
NEWS.txt
@ -1,3 +1,7 @@
|
||||
---------------- VERSION 3.0.8 --------------
|
||||
Bug Fixes:
|
||||
- Fixed installer bug on Windows. No other code changes.
|
||||
|
||||
---------------- VERSION 3.0.7 --------------
|
||||
|
||||
New features:
|
||||
|
@ -24,8 +24,10 @@ package org.sleuthkit.autopsy.recentactivity;
|
||||
|
||||
import com.google.gson.JsonArray;
|
||||
import com.google.gson.JsonElement;
|
||||
import com.google.gson.JsonIOException;
|
||||
import com.google.gson.JsonObject;
|
||||
import com.google.gson.JsonParser;
|
||||
import com.google.gson.JsonSyntaxException;
|
||||
import org.sleuthkit.autopsy.ingest.IngestServices;
|
||||
import org.sleuthkit.autopsy.datamodel.ContentUtils;
|
||||
import java.util.logging.Level;
|
||||
@ -36,7 +38,6 @@ import java.io.FileNotFoundException;
|
||||
import java.io.FileReader;
|
||||
import java.io.IOException;
|
||||
import org.sleuthkit.autopsy.casemodule.services.FileManager;
|
||||
import org.sleuthkit.autopsy.coreutils.EscapeUtil;
|
||||
import org.sleuthkit.autopsy.ingest.PipelineContext;
|
||||
import org.sleuthkit.autopsy.ingest.IngestDataSourceWorkerController;
|
||||
import org.sleuthkit.autopsy.ingest.IngestModuleDataSource;
|
||||
@ -94,7 +95,10 @@ public class Chrome extends Extract {
|
||||
try {
|
||||
historyFiles = fileManager.findFiles(dataSource, "History", "Chrome");
|
||||
} catch (TskCoreException ex) {
|
||||
logger.log(Level.SEVERE, "Error when trying to get Chrome history files.", ex);
|
||||
String msg = "Error when trying to get Chrome history files.";
|
||||
logger.log(Level.SEVERE, msg, ex);
|
||||
this.addErrorMessage(this.getName() + ": " + msg);
|
||||
return;
|
||||
}
|
||||
|
||||
// get only the allocated ones, for now
|
||||
@ -106,7 +110,7 @@ public class Chrome extends Extract {
|
||||
}
|
||||
|
||||
// log a message if we don't have any allocated history files
|
||||
if (allocatedHistoryFiles.size() == 0) {
|
||||
if (allocatedHistoryFiles.isEmpty()) {
|
||||
logger.log(Level.INFO, "Could not find any allocated Chrome history files.");
|
||||
return;
|
||||
}
|
||||
@ -114,7 +118,6 @@ public class Chrome extends Extract {
|
||||
int j = 0;
|
||||
while (j < historyFiles.size()) {
|
||||
String temps = RAImageIngestModule.getRATempPath(currentCase, "chrome") + File.separator + historyFiles.get(j).getName().toString() + j + ".db";
|
||||
int errors = 0;
|
||||
final AbstractFile historyFile = historyFiles.get(j++);
|
||||
if (historyFile.getSize() == 0) {
|
||||
continue;
|
||||
@ -149,10 +152,6 @@ public class Chrome extends Extract {
|
||||
this.addArtifact(ARTIFACT_TYPE.TSK_WEB_HISTORY, historyFile, bbattributes);
|
||||
|
||||
}
|
||||
if (errors > 0) {
|
||||
this.addErrorMessage(this.getName() + ": Error parsing " + errors + " Chrome web history artifacts.");
|
||||
}
|
||||
|
||||
dbFile.delete();
|
||||
}
|
||||
|
||||
@ -166,94 +165,109 @@ public class Chrome extends Extract {
|
||||
try {
|
||||
bookmarkFiles = fileManager.findFiles(dataSource, "Bookmarks", "Chrome");
|
||||
} catch (TskCoreException ex) {
|
||||
logger.log(Level.SEVERE, "Error when trying to get Chrome history files.", ex);
|
||||
String msg = "Error when trying to get Chrome Bookmark files.";
|
||||
logger.log(Level.SEVERE, msg, ex);
|
||||
this.addErrorMessage(this.getName() + ": " + msg);
|
||||
return;
|
||||
}
|
||||
|
||||
int j = 0;
|
||||
if (bookmarkFiles != null && !bookmarkFiles.isEmpty()) {
|
||||
while (j < bookmarkFiles.size()) {
|
||||
AbstractFile bookmarkFile = bookmarkFiles.get(j++);
|
||||
String temps = RAImageIngestModule.getRATempPath(currentCase, "chrome") + File.separator + bookmarkFile.getName().toString() + j + ".db";
|
||||
int errors = 0;
|
||||
try {
|
||||
ContentUtils.writeToFile(bookmarkFile, new File(temps));
|
||||
} catch (IOException ex) {
|
||||
logger.log(Level.SEVERE, "Error writing temp sqlite db for Chrome bookmark artifacts.{0}", ex);
|
||||
this.addErrorMessage(this.getName() + ": Error while trying to analyze file:" + bookmarkFile.getName());
|
||||
|
||||
while (j < bookmarkFiles.size()) {
|
||||
AbstractFile bookmarkFile = bookmarkFiles.get(j++);
|
||||
String temps = RAImageIngestModule.getRATempPath(currentCase, "chrome") + File.separator + bookmarkFile.getName().toString() + j + ".db";
|
||||
try {
|
||||
ContentUtils.writeToFile(bookmarkFile, new File(temps));
|
||||
} catch (IOException ex) {
|
||||
logger.log(Level.SEVERE, "Error writing temp sqlite db for Chrome bookmark artifacts.{0}", ex);
|
||||
this.addErrorMessage(this.getName() + ": Error while trying to analyze file:" + bookmarkFile.getName());
|
||||
continue;
|
||||
}
|
||||
|
||||
logger.log(Level.INFO, moduleName + "- Now getting Bookmarks from " + temps);
|
||||
File dbFile = new File(temps);
|
||||
if (controller.isCancelled()) {
|
||||
dbFile.delete();
|
||||
break;
|
||||
}
|
||||
|
||||
FileReader tempReader;
|
||||
try {
|
||||
tempReader = new FileReader(temps);
|
||||
} catch (FileNotFoundException ex) {
|
||||
logger.log(Level.SEVERE, "Error while trying to read into the Bookmarks for Chrome.", ex);
|
||||
this.addErrorMessage(this.getName() + ": Error while trying to analyze file: " + bookmarkFile.getName());
|
||||
continue;
|
||||
}
|
||||
|
||||
final JsonParser parser = new JsonParser();
|
||||
JsonElement jsonElement;
|
||||
JsonObject jElement, jRoot, jBookmark;
|
||||
JsonArray jBookmarkArray;
|
||||
|
||||
try {
|
||||
jsonElement = parser.parse(tempReader);
|
||||
jElement = jsonElement.getAsJsonObject();
|
||||
jRoot = jElement.get("roots").getAsJsonObject();
|
||||
jBookmark = jRoot.get("bookmark_bar").getAsJsonObject();
|
||||
jBookmarkArray = jBookmark.getAsJsonArray("children");
|
||||
} catch (JsonIOException | JsonSyntaxException | IllegalStateException ex) {
|
||||
logger.log(Level.WARNING, "Error parsing Json from Chrome Bookmark.", ex);
|
||||
this.addErrorMessage(this.getName() + ": Error while trying to analyze file: " + bookmarkFile.getName());
|
||||
continue;
|
||||
}
|
||||
|
||||
for (JsonElement result : jBookmarkArray) {
|
||||
JsonObject address = result.getAsJsonObject();
|
||||
if (address == null) {
|
||||
continue;
|
||||
}
|
||||
logger.log(Level.INFO, moduleName + "- Now getting Bookmarks from " + temps);
|
||||
File dbFile = new File(temps);
|
||||
if (controller.isCancelled()) {
|
||||
dbFile.delete();
|
||||
break;
|
||||
JsonElement urlEl = address.get("url");
|
||||
String url = null;
|
||||
if (urlEl != null) {
|
||||
url = urlEl.getAsString();
|
||||
}
|
||||
else {
|
||||
url = "";
|
||||
}
|
||||
String name = null;
|
||||
JsonElement nameEl = address.get("name");
|
||||
if (nameEl != null) {
|
||||
name = nameEl.getAsString();
|
||||
}
|
||||
else {
|
||||
name = "";
|
||||
}
|
||||
Long date = null;
|
||||
JsonElement dateEl = address.get("date_added");
|
||||
if (dateEl != null) {
|
||||
date = dateEl.getAsLong();
|
||||
}
|
||||
else {
|
||||
date = Long.valueOf(0);
|
||||
}
|
||||
String domain = Util.extractDomain(url);
|
||||
try {
|
||||
final JsonParser parser = new JsonParser();
|
||||
JsonElement jsonElement = parser.parse(new FileReader(temps));
|
||||
JsonObject jElement = jsonElement.getAsJsonObject();
|
||||
JsonObject jRoot = jElement.get("roots").getAsJsonObject();
|
||||
JsonObject jBookmark = jRoot.get("bookmark_bar").getAsJsonObject();
|
||||
JsonArray jBookmarkArray = jBookmark.getAsJsonArray("children");
|
||||
for (JsonElement result : jBookmarkArray) {
|
||||
try {
|
||||
JsonObject address = result.getAsJsonObject();
|
||||
if (address == null) {
|
||||
continue;
|
||||
}
|
||||
JsonElement urlEl = address.get("url");
|
||||
String url = null;
|
||||
if (urlEl != null) {
|
||||
url = urlEl.getAsString();
|
||||
}
|
||||
else {
|
||||
url = "";
|
||||
}
|
||||
String name = null;
|
||||
JsonElement nameEl = address.get("name");
|
||||
if (nameEl != null) {
|
||||
name = nameEl.getAsString();
|
||||
}
|
||||
else {
|
||||
name = "";
|
||||
}
|
||||
Long date = null;
|
||||
JsonElement dateEl = address.get("date_added");
|
||||
if (dateEl != null) {
|
||||
date = dateEl.getAsLong();
|
||||
}
|
||||
else {
|
||||
date = Long.valueOf(0);
|
||||
}
|
||||
String domain = Util.extractDomain(url);
|
||||
BlackboardArtifact bbart = bookmarkFile.newArtifact(ARTIFACT_TYPE.TSK_WEB_BOOKMARK);
|
||||
Collection<BlackboardAttribute> bbattributes = new ArrayList<BlackboardAttribute>();
|
||||
//TODO Revisit usage of deprecated constructor as per TSK-583
|
||||
//bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_LAST_ACCESSED.getTypeID(), "Recent Activity", "Last Visited", (date / 10000000)));
|
||||
bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DATETIME_ACCESSED.getTypeID(), "Recent Activity", (date / 10000000)));
|
||||
bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_URL.getTypeID(), "Recent Activity", url));
|
||||
//bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_URL_DECODED.getTypeID(), "Recent Activity", EscapeUtil.decodeURL(url)));
|
||||
bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_NAME.getTypeID(), "Recent Activity", name));
|
||||
bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_PROG_NAME.getTypeID(), "Recent Activity", "Chrome"));
|
||||
bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DOMAIN.getTypeID(), "Recent Activity", domain));
|
||||
bbart.addAttributes(bbattributes);
|
||||
} catch (TskCoreException ex) {
|
||||
logger.log(Level.SEVERE, "Error while trying to insert Chrom bookmark artifact{0}", ex);
|
||||
errors++;
|
||||
}
|
||||
}
|
||||
if (errors > 0) {
|
||||
this.addErrorMessage(this.getName() + ": Error parsing " + errors + " Chrome bookmark artifacts.");
|
||||
}
|
||||
} catch (FileNotFoundException ex) {
|
||||
logger.log(Level.SEVERE, "Error while trying to read into the Bookmarks for Chrome." + ex);
|
||||
BlackboardArtifact bbart = bookmarkFile.newArtifact(ARTIFACT_TYPE.TSK_WEB_BOOKMARK);
|
||||
Collection<BlackboardAttribute> bbattributes = new ArrayList<BlackboardAttribute>();
|
||||
//TODO Revisit usage of deprecated constructor as per TSK-583
|
||||
//bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_LAST_ACCESSED.getTypeID(), "Recent Activity", "Last Visited", (date / 10000000)));
|
||||
bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DATETIME_ACCESSED.getTypeID(), "Recent Activity", (date / 10000000)));
|
||||
bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_URL.getTypeID(), "Recent Activity", url));
|
||||
//bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_URL_DECODED.getTypeID(), "Recent Activity", EscapeUtil.decodeURL(url)));
|
||||
bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_NAME.getTypeID(), "Recent Activity", name));
|
||||
bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_PROG_NAME.getTypeID(), "Recent Activity", "Chrome"));
|
||||
bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DOMAIN.getTypeID(), "Recent Activity", domain));
|
||||
bbart.addAttributes(bbattributes);
|
||||
} catch (TskCoreException ex) {
|
||||
logger.log(Level.SEVERE, "Error while trying to insert Chrome bookmark artifact{0}", ex);
|
||||
this.addErrorMessage(this.getName() + ": Error while trying to analyze file:" + bookmarkFile.getName());
|
||||
}
|
||||
|
||||
dbFile.delete();
|
||||
}
|
||||
|
||||
services.fireModuleDataEvent(new ModuleDataEvent("Recent Activity", BlackboardArtifact.ARTIFACT_TYPE.TSK_WEB_BOOKMARK));
|
||||
dbFile.delete();
|
||||
}
|
||||
|
||||
services.fireModuleDataEvent(new ModuleDataEvent("Recent Activity", BlackboardArtifact.ARTIFACT_TYPE.TSK_WEB_BOOKMARK));
|
||||
}
|
||||
|
||||
//COOKIES section
|
||||
@ -265,56 +279,52 @@ public class Chrome extends Extract {
|
||||
try {
|
||||
cookiesFiles = fileManager.findFiles(dataSource, "Cookies", "Chrome");
|
||||
} catch (TskCoreException ex) {
|
||||
logger.log(Level.SEVERE, "Error when trying to get Chrome history files.", ex);
|
||||
String msg = "Error when trying to get Chrome history files.";
|
||||
logger.log(Level.SEVERE, msg, ex);
|
||||
this.addErrorMessage(this.getName() + ": " + msg);
|
||||
return;
|
||||
}
|
||||
|
||||
int j = 0;
|
||||
if (cookiesFiles != null && !cookiesFiles.isEmpty()) {
|
||||
while (j < cookiesFiles.size()) {
|
||||
AbstractFile cookiesFile = cookiesFiles.get(j++);
|
||||
String temps = RAImageIngestModule.getRATempPath(currentCase, "chrome") + File.separator + cookiesFile.getName().toString() + j + ".db";
|
||||
int errors = 0;
|
||||
try {
|
||||
ContentUtils.writeToFile(cookiesFile, new File(temps));
|
||||
} catch (IOException ex) {
|
||||
logger.log(Level.SEVERE, "Error writing temp sqlite db for Chrome cookie artifacts.{0}", ex);
|
||||
this.addErrorMessage(this.getName() + ": Error while trying to analyze file:" + cookiesFile.getName());
|
||||
continue;
|
||||
}
|
||||
File dbFile = new File(temps);
|
||||
if (controller.isCancelled()) {
|
||||
dbFile.delete();
|
||||
break;
|
||||
}
|
||||
|
||||
List<HashMap<String, Object>> tempList = this.dbConnect(temps, chcookiequery);
|
||||
logger.log(Level.INFO, moduleName + "- Now getting cookies from " + temps + " with " + tempList.size() + "artifacts identified.");
|
||||
for (HashMap<String, Object> result : tempList) {
|
||||
Collection<BlackboardAttribute> bbattributes = new ArrayList<BlackboardAttribute>();
|
||||
//TODO Revisit usage of deprecated constructor as per TSK-583
|
||||
//bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_NAME.getTypeID(), "Recent Activity", "Title", ((result.get("name").toString() != null) ? result.get("name").toString() : "")));
|
||||
//bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DATETIME.getTypeID(), "Recent Activity", "Last Visited", ((Long.valueOf(result.get("last_access_utc").toString())) / 10000000)));
|
||||
bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_NAME.getTypeID(), "Recent Activity", ((result.get("name").toString() != null) ? result.get("name").toString() : "")));
|
||||
bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DATETIME.getTypeID(), "Recent Activity", ((Long.valueOf(result.get("last_access_utc").toString())) / 10000000)));
|
||||
bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_VALUE.getTypeID(), "Recent Activity", ((result.get("value").toString() != null) ? result.get("value").toString() : "")));
|
||||
bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_PROG_NAME.getTypeID(), "Recent Activity", "Chrome"));
|
||||
bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_URL.getTypeID(), "Recent Activity", ((result.get("host_key").toString() != null) ? result.get("host_key").toString() : "")));
|
||||
//bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_URL_DECODED.getTypeID(), "Recent Activity", ((result.get("host_key").toString() != null) ? EscapeUtil.decodeURL(result.get("host_key").toString()) : "")));
|
||||
String domain = result.get("host_key").toString();
|
||||
domain = domain.replaceFirst("^\\.+(?!$)", "");
|
||||
bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DOMAIN.getTypeID(), "Recent Activity", domain));
|
||||
this.addArtifact(ARTIFACT_TYPE.TSK_WEB_COOKIE, cookiesFile, bbattributes);
|
||||
|
||||
}
|
||||
if (errors > 0) {
|
||||
this.addErrorMessage(this.getName() + ": Error parsing " + errors + " Chrome cookie artifacts.");
|
||||
}
|
||||
|
||||
while (j < cookiesFiles.size()) {
|
||||
AbstractFile cookiesFile = cookiesFiles.get(j++);
|
||||
String temps = RAImageIngestModule.getRATempPath(currentCase, "chrome") + File.separator + cookiesFile.getName().toString() + j + ".db";
|
||||
try {
|
||||
ContentUtils.writeToFile(cookiesFile, new File(temps));
|
||||
} catch (IOException ex) {
|
||||
logger.log(Level.SEVERE, "Error writing temp sqlite db for Chrome cookie artifacts.{0}", ex);
|
||||
this.addErrorMessage(this.getName() + ": Error while trying to analyze file:" + cookiesFile.getName());
|
||||
continue;
|
||||
}
|
||||
File dbFile = new File(temps);
|
||||
if (controller.isCancelled()) {
|
||||
dbFile.delete();
|
||||
break;
|
||||
}
|
||||
|
||||
services.fireModuleDataEvent(new ModuleDataEvent("Recent Activity", BlackboardArtifact.ARTIFACT_TYPE.TSK_WEB_COOKIE));
|
||||
List<HashMap<String, Object>> tempList = this.dbConnect(temps, chcookiequery);
|
||||
logger.log(Level.INFO, moduleName + "- Now getting cookies from " + temps + " with " + tempList.size() + "artifacts identified.");
|
||||
for (HashMap<String, Object> result : tempList) {
|
||||
Collection<BlackboardAttribute> bbattributes = new ArrayList<BlackboardAttribute>();
|
||||
//TODO Revisit usage of deprecated constructor as per TSK-583
|
||||
//bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_NAME.getTypeID(), "Recent Activity", "Title", ((result.get("name").toString() != null) ? result.get("name").toString() : "")));
|
||||
//bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DATETIME.getTypeID(), "Recent Activity", "Last Visited", ((Long.valueOf(result.get("last_access_utc").toString())) / 10000000)));
|
||||
bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_NAME.getTypeID(), "Recent Activity", ((result.get("name").toString() != null) ? result.get("name").toString() : "")));
|
||||
bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DATETIME.getTypeID(), "Recent Activity", ((Long.valueOf(result.get("last_access_utc").toString())) / 10000000)));
|
||||
bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_VALUE.getTypeID(), "Recent Activity", ((result.get("value").toString() != null) ? result.get("value").toString() : "")));
|
||||
bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_PROG_NAME.getTypeID(), "Recent Activity", "Chrome"));
|
||||
bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_URL.getTypeID(), "Recent Activity", ((result.get("host_key").toString() != null) ? result.get("host_key").toString() : "")));
|
||||
//bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_URL_DECODED.getTypeID(), "Recent Activity", ((result.get("host_key").toString() != null) ? EscapeUtil.decodeURL(result.get("host_key").toString()) : "")));
|
||||
String domain = result.get("host_key").toString();
|
||||
domain = domain.replaceFirst("^\\.+(?!$)", "");
|
||||
bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DOMAIN.getTypeID(), "Recent Activity", domain));
|
||||
this.addArtifact(ARTIFACT_TYPE.TSK_WEB_COOKIE, cookiesFile, bbattributes);
|
||||
}
|
||||
|
||||
dbFile.delete();
|
||||
}
|
||||
|
||||
services.fireModuleDataEvent(new ModuleDataEvent("Recent Activity", BlackboardArtifact.ARTIFACT_TYPE.TSK_WEB_COOKIE));
|
||||
}
|
||||
|
||||
//Downloads section
|
||||
@ -326,60 +336,57 @@ public class Chrome extends Extract {
|
||||
try {
|
||||
historyFiles = fileManager.findFiles(dataSource, "History", "Chrome");
|
||||
} catch (TskCoreException ex) {
|
||||
logger.log(Level.SEVERE, "Error when trying to get Chrome history files.", ex);
|
||||
String msg = "Error when trying to get Chrome history files.";
|
||||
logger.log(Level.SEVERE, msg, ex);
|
||||
this.addErrorMessage(this.getName() + ": " + msg);
|
||||
return;
|
||||
}
|
||||
|
||||
int j = 0;
|
||||
if (historyFiles != null && !historyFiles.isEmpty()) {
|
||||
while (j < historyFiles.size()) {
|
||||
AbstractFile historyFile = historyFiles.get(j++);
|
||||
if (historyFile.getSize() == 0) {
|
||||
continue;
|
||||
}
|
||||
String temps = RAImageIngestModule.getRATempPath(currentCase, "chrome") + File.separator + historyFile.getName().toString() + j + ".db";
|
||||
int errors = 0;
|
||||
try {
|
||||
ContentUtils.writeToFile(historyFile, new File(temps));
|
||||
} catch (IOException ex) {
|
||||
logger.log(Level.SEVERE, "Error writing temp sqlite db for Chrome download artifacts.{0}", ex);
|
||||
this.addErrorMessage(this.getName() + ": Error while trying to analyze file:" + historyFile.getName());
|
||||
continue;
|
||||
}
|
||||
File dbFile = new File(temps);
|
||||
if (controller.isCancelled()) {
|
||||
dbFile.delete();
|
||||
break;
|
||||
}
|
||||
|
||||
List<HashMap<String, Object>> tempList = this.dbConnect(temps, chdownloadquery);
|
||||
logger.log(Level.INFO, moduleName + "- Now getting downloads from " + temps + " with " + tempList.size() + "artifacts identified.");
|
||||
for (HashMap<String, Object> result : tempList) {
|
||||
Collection<BlackboardAttribute> bbattributes = new ArrayList<BlackboardAttribute>();
|
||||
bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_PATH.getTypeID(), "Recent Activity", (result.get("full_path").toString())));
|
||||
bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_PATH_ID.getTypeID(), "Recent Activity", Util.findID(dataSource, (result.get("full_path").toString()))));
|
||||
bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_URL.getTypeID(), "Recent Activity", ((result.get("url").toString() != null) ? result.get("url").toString() : "")));
|
||||
//bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_URL_DECODED.getTypeID(), "Recent Activity", ((result.get("url").toString() != null) ? EscapeUtil.decodeURL(result.get("url").toString()) : "")));
|
||||
Long time = (Long.valueOf(result.get("start_time").toString()));
|
||||
String Tempdate = time.toString();
|
||||
time = Long.valueOf(Tempdate) / 10000000;
|
||||
//TODO Revisit usage of deprecated constructor as per TSK-583
|
||||
//bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_LAST_ACCESSED.getTypeID(), "Recent Activity", "Last Visited", time));
|
||||
bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DATETIME_ACCESSED.getTypeID(), "Recent Activity", time));
|
||||
String domain = Util.extractDomain((result.get("url").toString() != null) ? result.get("url").toString() : "");
|
||||
bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DOMAIN.getTypeID(), "Recent Activity", domain));
|
||||
bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_PROG_NAME.getTypeID(), "Recent Activity", "Chrome"));
|
||||
this.addArtifact(ARTIFACT_TYPE.TSK_WEB_DOWNLOAD, historyFile, bbattributes);
|
||||
|
||||
}
|
||||
if (errors > 0) {
|
||||
this.addErrorMessage(this.getName() + ": Error parsing " + errors + " Chrome download artifacts.");
|
||||
}
|
||||
|
||||
while (j < historyFiles.size()) {
|
||||
AbstractFile historyFile = historyFiles.get(j++);
|
||||
if (historyFile.getSize() == 0) {
|
||||
continue;
|
||||
}
|
||||
String temps = RAImageIngestModule.getRATempPath(currentCase, "chrome") + File.separator + historyFile.getName().toString() + j + ".db";
|
||||
try {
|
||||
ContentUtils.writeToFile(historyFile, new File(temps));
|
||||
} catch (IOException ex) {
|
||||
logger.log(Level.SEVERE, "Error writing temp sqlite db for Chrome download artifacts.{0}", ex);
|
||||
this.addErrorMessage(this.getName() + ": Error while trying to analyze file:" + historyFile.getName());
|
||||
continue;
|
||||
}
|
||||
File dbFile = new File(temps);
|
||||
if (controller.isCancelled()) {
|
||||
dbFile.delete();
|
||||
break;
|
||||
}
|
||||
|
||||
services.fireModuleDataEvent(new ModuleDataEvent("Recent Activity", BlackboardArtifact.ARTIFACT_TYPE.TSK_WEB_DOWNLOAD));
|
||||
List<HashMap<String, Object>> tempList = this.dbConnect(temps, chdownloadquery);
|
||||
logger.log(Level.INFO, moduleName + "- Now getting downloads from " + temps + " with " + tempList.size() + "artifacts identified.");
|
||||
for (HashMap<String, Object> result : tempList) {
|
||||
Collection<BlackboardAttribute> bbattributes = new ArrayList<BlackboardAttribute>();
|
||||
bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_PATH.getTypeID(), "Recent Activity", (result.get("full_path").toString())));
|
||||
bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_PATH_ID.getTypeID(), "Recent Activity", Util.findID(dataSource, (result.get("full_path").toString()))));
|
||||
bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_URL.getTypeID(), "Recent Activity", ((result.get("url").toString() != null) ? result.get("url").toString() : "")));
|
||||
//bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_URL_DECODED.getTypeID(), "Recent Activity", ((result.get("url").toString() != null) ? EscapeUtil.decodeURL(result.get("url").toString()) : "")));
|
||||
Long time = (Long.valueOf(result.get("start_time").toString()));
|
||||
String Tempdate = time.toString();
|
||||
time = Long.valueOf(Tempdate) / 10000000;
|
||||
//TODO Revisit usage of deprecated constructor as per TSK-583
|
||||
//bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_LAST_ACCESSED.getTypeID(), "Recent Activity", "Last Visited", time));
|
||||
bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DATETIME_ACCESSED.getTypeID(), "Recent Activity", time));
|
||||
String domain = Util.extractDomain((result.get("url").toString() != null) ? result.get("url").toString() : "");
|
||||
bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DOMAIN.getTypeID(), "Recent Activity", domain));
|
||||
bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_PROG_NAME.getTypeID(), "Recent Activity", "Chrome"));
|
||||
this.addArtifact(ARTIFACT_TYPE.TSK_WEB_DOWNLOAD, historyFile, bbattributes);
|
||||
|
||||
}
|
||||
|
||||
dbFile.delete();
|
||||
}
|
||||
|
||||
services.fireModuleDataEvent(new ModuleDataEvent("Recent Activity", BlackboardArtifact.ARTIFACT_TYPE.TSK_WEB_DOWNLOAD));
|
||||
}
|
||||
|
||||
//Login/Password section
|
||||
@ -391,54 +398,50 @@ public class Chrome extends Extract {
|
||||
try {
|
||||
signonFiles = fileManager.findFiles(dataSource, "signons.sqlite", "Chrome");
|
||||
} catch (TskCoreException ex) {
|
||||
logger.log(Level.SEVERE, "Error when trying to get Chrome history files.", ex);
|
||||
String msg = "Error when trying to get Chrome history files.";
|
||||
logger.log(Level.SEVERE, msg, ex);
|
||||
this.addErrorMessage(this.getName() + ": " + msg);
|
||||
return;
|
||||
}
|
||||
|
||||
int j = 0;
|
||||
if (signonFiles != null && !signonFiles.isEmpty()) {
|
||||
while (j < signonFiles.size()) {
|
||||
AbstractFile signonFile = signonFiles.get(j++);
|
||||
String temps = RAImageIngestModule.getRATempPath(currentCase, "chrome") + File.separator + signonFile.getName().toString() + j + ".db";
|
||||
int errors = 0;
|
||||
try {
|
||||
ContentUtils.writeToFile(signonFile, new File(temps));
|
||||
} catch (IOException ex) {
|
||||
logger.log(Level.SEVERE, "Error writing temp sqlite db for Chrome login artifacts.{0}", ex);
|
||||
this.addErrorMessage(this.getName() + ": Error while trying to analyze file:" + signonFile.getName());
|
||||
continue;
|
||||
}
|
||||
File dbFile = new File(temps);
|
||||
if (controller.isCancelled()) {
|
||||
dbFile.delete();
|
||||
break;
|
||||
}
|
||||
List<HashMap<String, Object>> tempList = this.dbConnect(temps, chloginquery);
|
||||
logger.log(Level.INFO, moduleName + "- Now getting login information from " + temps + " with " + tempList.size() + "artifacts identified.");
|
||||
for (HashMap<String, Object> result : tempList) {
|
||||
Collection<BlackboardAttribute> bbattributes = new ArrayList<BlackboardAttribute>();
|
||||
bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_URL.getTypeID(), "Recent Activity", ((result.get("origin_url").toString() != null) ? result.get("origin_url").toString() : "")));
|
||||
//bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_URL_DECODED.getTypeID(), "Recent Activity", ((result.get("origin_url").toString() != null) ? EscapeUtil.decodeURL(result.get("origin_url").toString()) : "")));
|
||||
//TODO Revisit usage of deprecated constructor as per TSK-583
|
||||
//bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DATETIME_ACCESSED.getTypeID(), "Recent Activity", "Last Visited", ((Long.valueOf(result.get("last_visit_time").toString())) / 1000000)));
|
||||
bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DATETIME_ACCESSED.getTypeID(), "Recent Activity", ((Long.valueOf(result.get("last_visit_time").toString())) / 1000000)));
|
||||
bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_REFERRER.getTypeID(), "Recent Activity", ((result.get("from_visit").toString() != null) ? result.get("from_visit").toString() : "")));
|
||||
bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_NAME.getTypeID(), "Recent Activity", ((result.get("title").toString() != null) ? result.get("title").toString() : "")));
|
||||
bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_PROG_NAME.getTypeID(), "Recent Activity", "Chrome"));
|
||||
bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DOMAIN.getTypeID(), "Recent Activity", (Util.extractDomain((result.get("origin_url").toString() != null) ? result.get("url").toString() : ""))));
|
||||
bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_USER_NAME.getTypeID(), "Recent Activity", ((result.get("username_value").toString() != null) ? result.get("username_value").toString().replaceAll("'", "''") : "")));
|
||||
bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DOMAIN.getTypeID(), "Recent Activity", result.get("signon_realm").toString()));
|
||||
this.addArtifact(ARTIFACT_TYPE.TSK_WEB_HISTORY, signonFile, bbattributes);
|
||||
|
||||
}
|
||||
if (errors > 0) {
|
||||
this.addErrorMessage(this.getName() + ": Error parsing " + errors + " Chrome login artifacts.");
|
||||
}
|
||||
|
||||
while (j < signonFiles.size()) {
|
||||
AbstractFile signonFile = signonFiles.get(j++);
|
||||
String temps = RAImageIngestModule.getRATempPath(currentCase, "chrome") + File.separator + signonFile.getName().toString() + j + ".db";
|
||||
try {
|
||||
ContentUtils.writeToFile(signonFile, new File(temps));
|
||||
} catch (IOException ex) {
|
||||
logger.log(Level.SEVERE, "Error writing temp sqlite db for Chrome login artifacts.{0}", ex);
|
||||
this.addErrorMessage(this.getName() + ": Error while trying to analyze file:" + signonFile.getName());
|
||||
continue;
|
||||
}
|
||||
File dbFile = new File(temps);
|
||||
if (controller.isCancelled()) {
|
||||
dbFile.delete();
|
||||
break;
|
||||
}
|
||||
List<HashMap<String, Object>> tempList = this.dbConnect(temps, chloginquery);
|
||||
logger.log(Level.INFO, moduleName + "- Now getting login information from " + temps + " with " + tempList.size() + "artifacts identified.");
|
||||
for (HashMap<String, Object> result : tempList) {
|
||||
Collection<BlackboardAttribute> bbattributes = new ArrayList<BlackboardAttribute>();
|
||||
bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_URL.getTypeID(), "Recent Activity", ((result.get("origin_url").toString() != null) ? result.get("origin_url").toString() : "")));
|
||||
//bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_URL_DECODED.getTypeID(), "Recent Activity", ((result.get("origin_url").toString() != null) ? EscapeUtil.decodeURL(result.get("origin_url").toString()) : "")));
|
||||
//TODO Revisit usage of deprecated constructor as per TSK-583
|
||||
//bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DATETIME_ACCESSED.getTypeID(), "Recent Activity", "Last Visited", ((Long.valueOf(result.get("last_visit_time").toString())) / 1000000)));
|
||||
bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DATETIME_ACCESSED.getTypeID(), "Recent Activity", ((Long.valueOf(result.get("last_visit_time").toString())) / 1000000)));
|
||||
bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_REFERRER.getTypeID(), "Recent Activity", ((result.get("from_visit").toString() != null) ? result.get("from_visit").toString() : "")));
|
||||
bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_NAME.getTypeID(), "Recent Activity", ((result.get("title").toString() != null) ? result.get("title").toString() : "")));
|
||||
bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_PROG_NAME.getTypeID(), "Recent Activity", "Chrome"));
|
||||
bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DOMAIN.getTypeID(), "Recent Activity", (Util.extractDomain((result.get("origin_url").toString() != null) ? result.get("url").toString() : ""))));
|
||||
bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_USER_NAME.getTypeID(), "Recent Activity", ((result.get("username_value").toString() != null) ? result.get("username_value").toString().replaceAll("'", "''") : "")));
|
||||
bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DOMAIN.getTypeID(), "Recent Activity", result.get("signon_realm").toString()));
|
||||
this.addArtifact(ARTIFACT_TYPE.TSK_WEB_HISTORY, signonFile, bbattributes);
|
||||
}
|
||||
|
||||
services.fireModuleDataEvent(new ModuleDataEvent("Recent Activity", BlackboardArtifact.ARTIFACT_TYPE.TSK_WEB_HISTORY));
|
||||
dbFile.delete();
|
||||
}
|
||||
|
||||
services.fireModuleDataEvent(new ModuleDataEvent("Recent Activity", BlackboardArtifact.ARTIFACT_TYPE.TSK_WEB_HISTORY));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -46,7 +46,6 @@ import java.util.regex.Pattern;
|
||||
// TSK Imports
|
||||
import org.openide.modules.InstalledFileLocator;
|
||||
import org.sleuthkit.autopsy.casemodule.Case;
|
||||
import org.sleuthkit.autopsy.coreutils.EscapeUtil;
|
||||
import org.sleuthkit.autopsy.coreutils.JLNK;
|
||||
import org.sleuthkit.autopsy.coreutils.JLnkParser;
|
||||
import org.sleuthkit.autopsy.datamodel.ContentUtils;
|
||||
@ -96,66 +95,24 @@ public class ExtractIE extends Extract {
|
||||
|
||||
@Override
|
||||
public void process(PipelineContext<IngestModuleDataSource>pipelineContext, Content dataSource, IngestDataSourceWorkerController controller) {
|
||||
/* @@@ BC: All of these try / catches are added because the exception
|
||||
* handing in here isn't the best. We were losing results before because
|
||||
* cookies was throwing an exceptionb ecause of an invalid URL and we
|
||||
* skipped the rest of the data types. Need to push this eror handling
|
||||
* further down though.
|
||||
*/
|
||||
|
||||
try {
|
||||
this.extractAndRunPasco(dataSource, controller);
|
||||
}
|
||||
catch (Exception e) {
|
||||
logger.log(Level.SEVERE, "Error extracting IE index.dat files", e);
|
||||
addErrorMessage("Error extracting and analyzing IE index.dat files");
|
||||
}
|
||||
|
||||
try {
|
||||
this.getBookmark(dataSource, controller);
|
||||
}
|
||||
catch (Exception e) {
|
||||
logger.log(Level.SEVERE, "Error parsing IE bookmarks", e);
|
||||
addErrorMessage("Error parsing IE bookmarks");
|
||||
}
|
||||
|
||||
try {
|
||||
this.getCookie(dataSource, controller);
|
||||
}
|
||||
catch (Exception e) {
|
||||
logger.log(Level.SEVERE, "Error parsing IE cookies", e);
|
||||
addErrorMessage("Error parsing IE Cookies");
|
||||
}
|
||||
|
||||
try {
|
||||
this.getRecentDocuments(dataSource, controller);
|
||||
}
|
||||
catch (Exception e) {
|
||||
logger.log(Level.SEVERE, "Error parsing IE Recent Docs", e);
|
||||
addErrorMessage("Error parsing IE Recent Documents");
|
||||
}
|
||||
|
||||
try {
|
||||
this.getHistory(pascoResults);
|
||||
}
|
||||
catch (Exception e) {
|
||||
logger.log(Level.SEVERE, "Error parsing IE History", e);
|
||||
addErrorMessage("Error parsing IE History");
|
||||
}
|
||||
}
|
||||
|
||||
//Favorites section
|
||||
// This gets the favorite info
|
||||
private void getBookmark(Content dataSource, IngestDataSourceWorkerController controller) {
|
||||
|
||||
int errors = 0;
|
||||
|
||||
private void getBookmark(Content dataSource, IngestDataSourceWorkerController controller) {
|
||||
org.sleuthkit.autopsy.casemodule.services.FileManager fileManager = currentCase.getServices().getFileManager();
|
||||
List<AbstractFile> favoritesFiles = null;
|
||||
try {
|
||||
favoritesFiles = fileManager.findFiles(dataSource, "%.url", "Favorites");
|
||||
} catch (TskCoreException ex) {
|
||||
logger.log(Level.WARNING, "Error fetching 'index.data' files for Internet Explorer history.");
|
||||
logger.log(Level.WARNING, "Error fetching 'index.data' files for Internet Explorer history.", ex);
|
||||
this.addErrorMessage(this.getName() + ": Error getting Internet Explorer Bookmarks.");
|
||||
return;
|
||||
}
|
||||
|
||||
for (AbstractFile favoritesFile : favoritesFiles) {
|
||||
@ -168,6 +125,8 @@ public class ExtractIE extends Extract {
|
||||
final int bytesRead = fav.read(t, 0, fav.getSize());
|
||||
} catch (TskCoreException ex) {
|
||||
logger.log(Level.SEVERE, "Error reading bytes of Internet Explorer favorite.", ex);
|
||||
this.addErrorMessage(this.getName() + ": Error reading Internet Explorer Bookmark file " + favoritesFile.getName());
|
||||
continue;
|
||||
}
|
||||
String bookmarkString = new String(t);
|
||||
String re1 = ".*?"; // Non-greedy match on filler
|
||||
@ -197,9 +156,6 @@ public class ExtractIE extends Extract {
|
||||
|
||||
services.fireModuleDataEvent(new ModuleDataEvent("Recent Activity", BlackboardArtifact.ARTIFACT_TYPE.TSK_WEB_BOOKMARK));
|
||||
}
|
||||
if (errors > 0) {
|
||||
this.addErrorMessage(this.getName() + ": Error parsing " + errors + " Internet Explorer favorites.");
|
||||
}
|
||||
}
|
||||
|
||||
//Cookies section
|
||||
@ -212,9 +168,10 @@ public class ExtractIE extends Extract {
|
||||
cookiesFiles = fileManager.findFiles(dataSource, "%.txt", "Cookies");
|
||||
} catch (TskCoreException ex) {
|
||||
logger.log(Level.WARNING, "Error fetching 'index.data' files for Internet Explorer history.");
|
||||
this.addErrorMessage(this.getName() + ": " + "Error getting Internet Explorer cookie files.");
|
||||
return;
|
||||
}
|
||||
|
||||
int errors = 0;
|
||||
for (AbstractFile cookiesFile : cookiesFiles) {
|
||||
if (controller.isCancelled()) {
|
||||
break;
|
||||
@ -225,6 +182,8 @@ public class ExtractIE extends Extract {
|
||||
final int bytesRead = fav.read(t, 0, fav.getSize());
|
||||
} catch (TskCoreException ex) {
|
||||
logger.log(Level.SEVERE, "Error reading bytes of Internet Explorer cookie.", ex);
|
||||
this.addErrorMessage(this.getName() + ": Error reading Internet Explorer cookie " + cookiesFile.getName());
|
||||
continue;
|
||||
}
|
||||
String cookieString = new String(t);
|
||||
String[] values = cookieString.split("\n");
|
||||
@ -232,8 +191,8 @@ public class ExtractIE extends Extract {
|
||||
String value = values.length > 1 ? values[1] : "";
|
||||
String name = values.length > 0 ? values[0] : "";
|
||||
Long datetime = cookiesFile.getCrtime();
|
||||
String Tempdate = datetime.toString();
|
||||
datetime = Long.valueOf(Tempdate);
|
||||
String tempDate = datetime.toString();
|
||||
datetime = Long.valueOf(tempDate);
|
||||
String domain = Util.extractDomain(url);
|
||||
|
||||
Collection<BlackboardAttribute> bbattributes = new ArrayList<BlackboardAttribute>();
|
||||
@ -250,9 +209,6 @@ public class ExtractIE extends Extract {
|
||||
bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DOMAIN.getTypeID(), "RecentActivity", domain));
|
||||
this.addArtifact(ARTIFACT_TYPE.TSK_WEB_COOKIE, cookiesFile, bbattributes);
|
||||
}
|
||||
if (errors > 0) {
|
||||
this.addErrorMessage(this.getName() + ": Error parsing " + errors + " Internet Explorer cookies.");
|
||||
}
|
||||
|
||||
services.fireModuleDataEvent(new ModuleDataEvent("Recent Activity", BlackboardArtifact.ARTIFACT_TYPE.TSK_WEB_COOKIE));
|
||||
}
|
||||
@ -267,6 +223,8 @@ public class ExtractIE extends Extract {
|
||||
recentFiles = fileManager.findFiles(dataSource, "%.lnk", "Recent");
|
||||
} catch (TskCoreException ex) {
|
||||
logger.log(Level.WARNING, "Error fetching 'index.data' files for Internet Explorer history.");
|
||||
this.addErrorMessage(this.getName() + ": Error getting Recent Files.");
|
||||
return;
|
||||
}
|
||||
|
||||
for (AbstractFile recentFile : recentFiles) {
|
||||
@ -281,10 +239,10 @@ public class ExtractIE extends Extract {
|
||||
JLnkParser lnkParser = new JLnkParser(new ReadContentInputStream(fav), (int) fav.getSize());
|
||||
try {
|
||||
lnk = lnkParser.parse();
|
||||
}
|
||||
catch (Exception e) {
|
||||
} catch (Exception e) {
|
||||
//TODO should throw a specific checked exception
|
||||
logger.log(Level.SEVERE, "Error lnk parsing the file to get recent files" + recentFile);
|
||||
this.addErrorMessage(this.getName() + ": Error parsing Recent File " + recentFile.getName());
|
||||
continue;
|
||||
}
|
||||
String path = lnk.getBestPath();
|
||||
@ -335,7 +293,9 @@ public class ExtractIE extends Extract {
|
||||
try {
|
||||
indexFiles = fileManager.findFiles(dataSource, "index.dat");
|
||||
} catch (TskCoreException ex) {
|
||||
this.addErrorMessage(this.getName() + ": Error getting Internet Explorer history files");
|
||||
logger.log(Level.WARNING, "Error fetching 'index.data' files for Internet Explorer history.");
|
||||
return;
|
||||
}
|
||||
|
||||
String temps;
|
||||
@ -417,137 +377,118 @@ public class ExtractIE extends Extract {
|
||||
}
|
||||
|
||||
private void getHistory(List<String> filenames) {
|
||||
if (pascoFound == false) {
|
||||
// Make sure pasco and the results exist
|
||||
File rFile = new File(moduleTempResultsDir);
|
||||
if (pascoFound == false || ! rFile.exists()) {
|
||||
return;
|
||||
}
|
||||
// First thing we want to do is check to make sure the results directory
|
||||
// is not empty.
|
||||
File rFile = new File(moduleTempResultsDir);
|
||||
|
||||
if (rFile.exists()) {
|
||||
//Give me a list of pasco results in that directory
|
||||
File[] pascoFiles = rFile.listFiles();
|
||||
//Give me a list of pasco results in that directory
|
||||
File[] pascoFiles = rFile.listFiles();
|
||||
for (File file : pascoFiles) {
|
||||
String fileName = file.getName();
|
||||
if (!filenames.contains(fileName)) {
|
||||
logger.log(Level.INFO, "Found a temp Pasco result file not in the list: {0}", fileName);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (pascoFiles.length > 0) {
|
||||
for (File file : pascoFiles) {
|
||||
String fileName = file.getName();
|
||||
if (!filenames.contains(fileName)) {
|
||||
logger.log(Level.INFO, "Found a temp Pasco result file not in the list: {0}", fileName);
|
||||
continue;
|
||||
}
|
||||
long artObjId = Long.parseLong(fileName.substring(fileName.indexOf(".") + 1, fileName.lastIndexOf(".")));
|
||||
// Make sure the file the is not empty or the Scanner will
|
||||
// throw a "No Line found" Exception
|
||||
if (file.length() == 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Make sure the file the is not empty or the Scanner will
|
||||
// throw a "No Line found" Exception
|
||||
if (file != null && file.length() > 0) {
|
||||
try {
|
||||
Scanner fileScanner = new Scanner(new FileInputStream(file.toString()));
|
||||
//Skip the first three lines
|
||||
fileScanner.nextLine();
|
||||
fileScanner.nextLine();
|
||||
fileScanner.nextLine();
|
||||
long artObjId = Long.parseLong(fileName.substring(fileName.indexOf(".") + 1, fileName.lastIndexOf(".")));
|
||||
Scanner fileScanner;
|
||||
try {
|
||||
fileScanner = new Scanner(new FileInputStream(file.toString()));
|
||||
} catch (FileNotFoundException ex) {
|
||||
this.addErrorMessage(this.getName() + ": Error parsing IE history entry " + file.getName());
|
||||
logger.log(Level.WARNING, "Unable to find the Pasco file at " + file.getPath(), ex);
|
||||
continue;
|
||||
}
|
||||
|
||||
while (fileScanner.hasNext()) {
|
||||
String line = fileScanner.nextLine();
|
||||
if (!line.startsWith("URL")) {
|
||||
continue;
|
||||
}
|
||||
|
||||
while (fileScanner.hasNext()) {
|
||||
String[] lineBuff = line.split("\\t");
|
||||
|
||||
String line = fileScanner.nextLine();
|
||||
if (lineBuff.length < 4) {
|
||||
logger.log(Level.INFO, "Found unrecognized IE history format.");
|
||||
continue;
|
||||
}
|
||||
|
||||
// lines at end of file
|
||||
if ((line.startsWith("LEAK entries")) ||
|
||||
(line.startsWith("REDR entries")) ||
|
||||
(line.startsWith("URL entries")) ||
|
||||
(line.startsWith("ent entries")) ||
|
||||
(line.startsWith("unknown entries"))) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (line.startsWith("URL")) {
|
||||
String[] lineBuff = line.split("\\t");
|
||||
|
||||
if (lineBuff.length < 4) {
|
||||
// @@@ Could log a message here
|
||||
continue;
|
||||
}
|
||||
|
||||
String ddtime = lineBuff[2];
|
||||
String actime = lineBuff[3];
|
||||
Long ftime = (long) 0;
|
||||
String user = "";
|
||||
String realurl = "";
|
||||
String domain = "";
|
||||
|
||||
/* We've seen two types of lines:
|
||||
* URL http://XYZ.com ....
|
||||
* URL Visited: Joe@http://XYZ.com ....
|
||||
*/
|
||||
if (lineBuff[1].contains("@")) {
|
||||
String url[] = lineBuff[1].split("@", 2);
|
||||
user = url[0];
|
||||
user = user.replace("Visited:", "");
|
||||
user = user.replace(":Host:", "");
|
||||
user = user.replaceAll("(:)(.*?)(:)", "");
|
||||
user = user.trim();
|
||||
realurl = url[1];
|
||||
realurl = realurl.replace("Visited:", "");
|
||||
realurl = realurl.replaceAll(":(.*?):", "");
|
||||
realurl = realurl.replace(":Host:", "");
|
||||
realurl = realurl.trim();
|
||||
}
|
||||
else {
|
||||
user = "";
|
||||
realurl = lineBuff[1].trim();
|
||||
}
|
||||
|
||||
domain = Util.extractDomain(realurl);
|
||||
|
||||
if (!ddtime.isEmpty()) {
|
||||
ddtime = ddtime.replace("T", " ");
|
||||
ddtime = ddtime.substring(ddtime.length() - 5);
|
||||
}
|
||||
|
||||
if (!actime.isEmpty()) {
|
||||
try {
|
||||
Long epochtime = dateFormatter.parse(actime).getTime();
|
||||
ftime = epochtime.longValue();
|
||||
ftime = ftime / 1000;
|
||||
} catch (ParseException e) {
|
||||
logger.log(Level.SEVERE, "Error parsing Pasco results.", e);
|
||||
}
|
||||
}
|
||||
String ddtime = lineBuff[2];
|
||||
String actime = lineBuff[3];
|
||||
Long ftime = (long) 0;
|
||||
String user = "";
|
||||
String realurl = "";
|
||||
String domain = "";
|
||||
|
||||
try {
|
||||
BlackboardArtifact bbart = tskCase.getContentById(artObjId).newArtifact(ARTIFACT_TYPE.TSK_WEB_HISTORY);
|
||||
Collection<BlackboardAttribute> bbattributes = new ArrayList<BlackboardAttribute>();
|
||||
bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_URL.getTypeID(), "RecentActivity", realurl));
|
||||
//bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_URL_DECODED.getTypeID(), "RecentActivity", EscapeUtil.decodeURL(realurl)));
|
||||
/* We've seen two types of lines:
|
||||
* URL http://XYZ.com ....
|
||||
* URL Visited: Joe@http://XYZ.com ....
|
||||
*/
|
||||
if (lineBuff[1].contains("@")) {
|
||||
String url[] = lineBuff[1].split("@", 2);
|
||||
user = url[0];
|
||||
user = user.replace("Visited:", "");
|
||||
user = user.replace(":Host:", "");
|
||||
user = user.replaceAll("(:)(.*?)(:)", "");
|
||||
user = user.trim();
|
||||
realurl = url[1];
|
||||
realurl = realurl.replace("Visited:", "");
|
||||
realurl = realurl.replaceAll(":(.*?):", "");
|
||||
realurl = realurl.replace(":Host:", "");
|
||||
realurl = realurl.trim();
|
||||
} else {
|
||||
user = "";
|
||||
realurl = lineBuff[1].trim();
|
||||
}
|
||||
|
||||
bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DATETIME_ACCESSED.getTypeID(), "RecentActivity", ftime));
|
||||
domain = Util.extractDomain(realurl);
|
||||
|
||||
bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_REFERRER.getTypeID(), "RecentActivity", ""));
|
||||
if (!ddtime.isEmpty()) {
|
||||
ddtime = ddtime.replace("T", " ");
|
||||
ddtime = ddtime.substring(ddtime.length() - 5);
|
||||
}
|
||||
|
||||
// bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DATETIME.getTypeID(), "RecentActivity", ddtime));
|
||||
|
||||
bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_PROG_NAME.getTypeID(), "RecentActivity", "Internet Explorer"));
|
||||
bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DOMAIN.getTypeID(), "RecentActivity", domain));
|
||||
bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_USER_NAME.getTypeID(), "RecentActivity", user));
|
||||
bbart.addAttributes(bbattributes);
|
||||
} catch (TskCoreException ex) {
|
||||
logger.log(Level.SEVERE, "Error writing Internet Explorer web history artifact to the blackboard.", ex);
|
||||
}
|
||||
}
|
||||
else {
|
||||
// @@@ Log that we didn't parse this
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
} catch (FileNotFoundException ex) {
|
||||
logger.log(Level.WARNING, "Unable to find the Pasco file at " + file.getPath(), ex);
|
||||
}
|
||||
if (!actime.isEmpty()) {
|
||||
try {
|
||||
Long epochtime = dateFormatter.parse(actime).getTime();
|
||||
ftime = epochtime.longValue();
|
||||
ftime = ftime / 1000;
|
||||
} catch (ParseException e) {
|
||||
this.addErrorMessage(this.getName() + ": Error parsing Internet Explorer History entry.");
|
||||
logger.log(Level.SEVERE, "Error parsing Pasco results.", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
BlackboardArtifact bbart = tskCase.getContentById(artObjId).newArtifact(ARTIFACT_TYPE.TSK_WEB_HISTORY);
|
||||
Collection<BlackboardAttribute> bbattributes = new ArrayList<BlackboardAttribute>();
|
||||
bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_URL.getTypeID(), "RecentActivity", realurl));
|
||||
//bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_URL_DECODED.getTypeID(), "RecentActivity", EscapeUtil.decodeURL(realurl)));
|
||||
|
||||
bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DATETIME_ACCESSED.getTypeID(), "RecentActivity", ftime));
|
||||
|
||||
bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_REFERRER.getTypeID(), "RecentActivity", ""));
|
||||
|
||||
// bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DATETIME.getTypeID(), "RecentActivity", ddtime));
|
||||
|
||||
bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_PROG_NAME.getTypeID(), "RecentActivity", "Internet Explorer"));
|
||||
bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DOMAIN.getTypeID(), "RecentActivity", domain));
|
||||
bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_USER_NAME.getTypeID(), "RecentActivity", user));
|
||||
bbart.addAttributes(bbattributes);
|
||||
} catch (TskCoreException ex) {
|
||||
logger.log(Level.SEVERE, "Error writing Internet Explorer web history artifact to the blackboard.", ex);
|
||||
}
|
||||
}
|
||||
fileScanner.close();
|
||||
}
|
||||
services.fireModuleDataEvent(new ModuleDataEvent("Recent Activity", BlackboardArtifact.ARTIFACT_TYPE.TSK_WEB_HISTORY));
|
||||
}
|
||||
|
||||
|
@ -133,7 +133,9 @@ public class ExtractRegistry extends Extract {
|
||||
try {
|
||||
allRegistryFiles.addAll(fileManager.findFiles(dataSource, regFileName, "/system32/config"));
|
||||
} catch (TskCoreException ex) {
|
||||
logger.log(Level.WARNING, "Error fetching registry file: " + regFileName);
|
||||
String msg = "Error fetching registry file: " + regFileName;
|
||||
logger.log(Level.WARNING, msg);
|
||||
this.addErrorMessage(this.getName() + ": " + msg);
|
||||
}
|
||||
}
|
||||
ExtractUSB extrctr = new ExtractUSB();
|
||||
@ -155,6 +157,7 @@ public class ExtractRegistry extends Extract {
|
||||
ContentUtils.writeToFile(regFile, regFileNameLocalFile);
|
||||
} catch (IOException ex) {
|
||||
logger.log(Level.SEVERE, "Error writing the temp registry file. {0}", ex);
|
||||
this.addErrorMessage(this.getName() + ": Error analyzing registry file " + regFileName);
|
||||
continue;
|
||||
}
|
||||
|
||||
@ -164,14 +167,14 @@ public class ExtractRegistry extends Extract {
|
||||
}
|
||||
} catch (TskCoreException ex) {
|
||||
java.util.logging.Logger.getLogger(ExtractRegistry.class.getName()).log(Level.SEVERE, null, ex);
|
||||
}
|
||||
catch (IOException ex) {
|
||||
} catch (IOException ex) {
|
||||
java.util.logging.Logger.getLogger(ExtractRegistry.class.getName()).log(Level.SEVERE, null, ex);
|
||||
}
|
||||
|
||||
logger.log(Level.INFO, moduleName + "- Now getting registry information from " + regFileNameLocal);
|
||||
RegOutputFiles regOutputFiles = executeRegRip(regFileNameLocal, outputPathBase);
|
||||
if (parseReg(regOutputFiles.autopsyPlugins, regFile.getId(), extrctr) == false) {
|
||||
this.addErrorMessage(this.getName() + ": Failed parsing registry file results " + regFileName);
|
||||
continue;
|
||||
}
|
||||
|
||||
@ -184,30 +187,37 @@ public class ExtractRegistry extends Extract {
|
||||
BufferedReader input = new BufferedReader(fread);
|
||||
|
||||
StringBuilder sb = new StringBuilder();
|
||||
while (true) {
|
||||
|
||||
try {
|
||||
try {
|
||||
while (true) {
|
||||
String s = input.readLine();
|
||||
if (s == null) {
|
||||
break;
|
||||
}
|
||||
sb.append(s).append("\n");
|
||||
}
|
||||
} catch (IOException ex) {
|
||||
java.util.logging.Logger.getLogger(ExtractRegistry.class.getName()).log(Level.SEVERE, null, ex);
|
||||
} finally {
|
||||
try {
|
||||
input.close();
|
||||
} catch (IOException ex) {
|
||||
java.util.logging.Logger.getLogger(ExtractRegistry.class.getName()).log(Level.SEVERE, null, ex);
|
||||
break;
|
||||
logger.log(Level.WARNING, "Failed to close reader.", ex);
|
||||
}
|
||||
}
|
||||
|
||||
att = new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_TEXT.getTypeID(), "RecentActivity", sb.toString());
|
||||
art.addAttribute(att);
|
||||
} catch (FileNotFoundException ex) {
|
||||
this.addErrorMessage(this.getName() + ": Error reading registry file - " + regOutputFiles.fullPlugins);
|
||||
java.util.logging.Logger.getLogger(ExtractRegistry.class.getName()).log(Level.SEVERE, null, ex);
|
||||
} catch (TskCoreException ex) {
|
||||
// TODO - add error message here?
|
||||
java.util.logging.Logger.getLogger(ExtractRegistry.class.getName()).log(Level.SEVERE, null, ex);
|
||||
}
|
||||
}
|
||||
|
||||
regFileNameLocalFile.delete();
|
||||
}
|
||||
|
||||
try {
|
||||
if (logFile != null) {
|
||||
logFile.close();
|
||||
@ -256,7 +266,8 @@ public class ExtractRegistry extends Extract {
|
||||
type = "1default";
|
||||
}
|
||||
|
||||
if ((type.equals("") == false) && (rrFound)) {
|
||||
if (!type.isEmpty() && rrFound) {
|
||||
// TODO - add error messages
|
||||
try {
|
||||
regOutputFiles.autopsyPlugins = outFilePathBase + "-autopsy.txt";
|
||||
logger.log(Level.INFO, "Writing RegRipper results to: " + regOutputFiles.autopsyPlugins);
|
||||
@ -266,8 +277,10 @@ public class ExtractRegistry extends Extract {
|
||||
"-r", regFilePath, "-f", type);
|
||||
} catch (IOException ex) {
|
||||
logger.log(Level.SEVERE, "Unable to RegRipper and process parse some registry files.", ex);
|
||||
this.addErrorMessage(this.getName() + ": Failed to analyze registry file");
|
||||
} catch (InterruptedException ex) {
|
||||
logger.log(Level.SEVERE, "RegRipper has been interrupted, failed to parse registry.", ex);
|
||||
this.addErrorMessage(this.getName() + ": Failed to analyze registry file");
|
||||
} finally {
|
||||
if (writer != null) {
|
||||
try {
|
||||
@ -282,7 +295,7 @@ public class ExtractRegistry extends Extract {
|
||||
logger.log(Level.INFO, "Not running Autopsy-only modules on hive");
|
||||
}
|
||||
|
||||
if ((fullType.equals("") == false) && (rrFullFound)) {
|
||||
if (!fullType.isEmpty() && rrFullFound) {
|
||||
try {
|
||||
regOutputFiles.fullPlugins = outFilePathBase + "-full.txt";
|
||||
logger.log(Level.INFO, "Writing Full RegRipper results to: " + regOutputFiles.fullPlugins);
|
||||
@ -292,8 +305,10 @@ public class ExtractRegistry extends Extract {
|
||||
"-r", regFilePath, "-f", fullType);
|
||||
} catch (IOException ex) {
|
||||
logger.log(Level.SEVERE, "Unable to run full RegRipper and process parse some registry files.", ex);
|
||||
this.addErrorMessage(this.getName() + ": Failed to analyze registry file");
|
||||
} catch (InterruptedException ex) {
|
||||
logger.log(Level.SEVERE, "RegRipper full has been interrupted, failed to parse registry.", ex);
|
||||
this.addErrorMessage(this.getName() + ": Failed to analyze registry file");
|
||||
} finally {
|
||||
if (writer != null) {
|
||||
try {
|
||||
|
@ -32,7 +32,6 @@ import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.logging.Level;
|
||||
import org.sleuthkit.autopsy.casemodule.services.FileManager;
|
||||
import org.sleuthkit.autopsy.coreutils.EscapeUtil;
|
||||
import org.sleuthkit.autopsy.datamodel.ContentUtils;
|
||||
import org.sleuthkit.autopsy.ingest.PipelineContext;
|
||||
import org.sleuthkit.autopsy.ingest.IngestDataSourceWorkerController;
|
||||
@ -90,18 +89,15 @@ public class Firefox extends Extract {
|
||||
try {
|
||||
historyFiles = fileManager.findFiles(dataSource, "%places.sqlite%", "Firefox");
|
||||
} catch (TskCoreException ex) {
|
||||
logger.log(Level.WARNING, "Error fetching internet history files for Firefox.");
|
||||
}
|
||||
|
||||
if (historyFiles == null) {
|
||||
return;
|
||||
String msg = "Error fetching internet history files for Firefox.";
|
||||
logger.log(Level.WARNING, msg);
|
||||
this.addErrorMessage(this.getName() + ": " + msg);
|
||||
}
|
||||
|
||||
int j = 0;
|
||||
for (AbstractFile historyFile : historyFiles) {
|
||||
String fileName = historyFile.getName();
|
||||
String temps = RAImageIngestModule.getRATempPath(currentCase, "firefox") + File.separator + fileName + j + ".db";
|
||||
int errors = 0;
|
||||
try {
|
||||
ContentUtils.writeToFile(historyFile, new File(temps));
|
||||
} catch (IOException ex) {
|
||||
@ -130,9 +126,6 @@ public class Firefox extends Extract {
|
||||
this.addArtifact(ARTIFACT_TYPE.TSK_WEB_HISTORY, historyFile, bbattributes);
|
||||
|
||||
}
|
||||
if (errors > 0) {
|
||||
this.addErrorMessage(this.getName() + ": Error parsing " + errors + " Firefox web history artifacts.");
|
||||
}
|
||||
++j;
|
||||
dbFile.delete();
|
||||
}
|
||||
@ -147,10 +140,9 @@ public class Firefox extends Extract {
|
||||
try {
|
||||
bookmarkFiles = fileManager.findFiles(dataSource, "places.sqlite", "Firefox");
|
||||
} catch (TskCoreException ex) {
|
||||
logger.log(Level.WARNING, "Error fetching bookmark files for Firefox.");
|
||||
}
|
||||
|
||||
if (bookmarkFiles == null) {
|
||||
String msg = "Error fetching bookmark files for Firefox.";
|
||||
logger.log(Level.WARNING, msg);
|
||||
this.addErrorMessage(this.getName() + ": " + msg);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -158,7 +150,6 @@ public class Firefox extends Extract {
|
||||
for (AbstractFile bookmarkFile : bookmarkFiles) {
|
||||
String fileName = bookmarkFile.getName();
|
||||
String temps = RAImageIngestModule.getRATempPath(currentCase, "firefox") + File.separator + fileName + j + ".db";
|
||||
int errors = 0;
|
||||
try {
|
||||
ContentUtils.writeToFile(bookmarkFile, new File(temps));
|
||||
} catch (IOException ex) {
|
||||
@ -184,9 +175,6 @@ public class Firefox extends Extract {
|
||||
this.addArtifact(ARTIFACT_TYPE.TSK_WEB_BOOKMARK, bookmarkFile, bbattributes);
|
||||
|
||||
}
|
||||
if (errors > 0) {
|
||||
this.addErrorMessage(this.getName() + ": Error parsing " + errors + " Firefox web history artifacts.");
|
||||
}
|
||||
++j;
|
||||
dbFile.delete();
|
||||
}
|
||||
@ -203,10 +191,9 @@ public class Firefox extends Extract {
|
||||
try {
|
||||
cookiesFiles = fileManager.findFiles(dataSource, "cookies.sqlite", "Firefox");
|
||||
} catch (TskCoreException ex) {
|
||||
logger.log(Level.WARNING, "Error fetching cookies files for Firefox.");
|
||||
}
|
||||
|
||||
if (cookiesFiles == null) {
|
||||
String msg = "Error fetching cookies files for Firefox.";
|
||||
logger.log(Level.WARNING, msg);
|
||||
this.addErrorMessage(this.getName() + ": " + msg);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -214,7 +201,6 @@ public class Firefox extends Extract {
|
||||
for (AbstractFile cookiesFile : cookiesFiles) {
|
||||
String fileName = cookiesFile.getName();
|
||||
String temps = RAImageIngestModule.getRATempPath(currentCase, "firefox") + File.separator + fileName + j + ".db";
|
||||
int errors = 0;
|
||||
try {
|
||||
ContentUtils.writeToFile(cookiesFile, new File(temps));
|
||||
} catch (IOException ex) {
|
||||
@ -261,9 +247,6 @@ public class Firefox extends Extract {
|
||||
this.addArtifact(ARTIFACT_TYPE.TSK_WEB_COOKIE, cookiesFile, bbattributes);
|
||||
|
||||
}
|
||||
if (errors > 0) {
|
||||
this.addErrorMessage(this.getName() + ": Error parsing " + errors + " Firefox web history artifacts.");
|
||||
}
|
||||
++j;
|
||||
dbFile.delete();
|
||||
}
|
||||
@ -280,10 +263,9 @@ public class Firefox extends Extract {
|
||||
try {
|
||||
downloadsFiles = fileManager.findFiles(dataSource, "downloads.sqlite", "Firefox");
|
||||
} catch (TskCoreException ex) {
|
||||
logger.log(Level.WARNING, "Error fetching 'downloads' files for Firefox.");
|
||||
}
|
||||
|
||||
if (downloadsFiles == null) {
|
||||
String msg = "Error fetching 'downloads' files for Firefox.";
|
||||
logger.log(Level.WARNING, msg);
|
||||
this.addErrorMessage(this.getName() + ": " + msg);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -77,7 +77,7 @@ public final class RAImageIngestModule extends IngestModuleDataSource {
|
||||
} catch (Exception ex) {
|
||||
logger.log(Level.SEVERE, "Exception occurred in " + module.getName(), ex);
|
||||
subCompleted.append(module.getName()).append(" failed - see log for details <br>");
|
||||
errors.add(module.getName() + "had errors -- see log");
|
||||
errors.add(module.getName() + " had errors -- see log");
|
||||
}
|
||||
controller.progress(i + 1);
|
||||
errors.addAll(module.getErrorMessages());
|
||||
|
@ -27,7 +27,6 @@ import java.net.URLDecoder;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.logging.Level;
|
||||
@ -48,7 +47,6 @@ import org.sleuthkit.datamodel.BlackboardArtifact.ARTIFACT_TYPE;
|
||||
import org.sleuthkit.datamodel.BlackboardAttribute;
|
||||
import org.sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE;
|
||||
import org.sleuthkit.datamodel.Content;
|
||||
import org.sleuthkit.datamodel.FsContent;
|
||||
import org.sleuthkit.datamodel.TskException;
|
||||
import org.w3c.dom.Document;
|
||||
import org.w3c.dom.NamedNodeMap;
|
||||
|
@ -84,6 +84,14 @@
|
||||
<var name="jre-path" value="${env.JRE_HOME_32}"/>
|
||||
<var name="package-type" value="x86" />
|
||||
<var name="jvm.max.mem" value="512" />
|
||||
<var name="new-jre-path" value="${inst-path}\jre"/>
|
||||
<delete failonerror="false" dir="${new-jre-path}"/>
|
||||
<mkdir dir="${new-jre-path}"/>
|
||||
<copy todir="${new-jre-path}" overwrite="true">
|
||||
<fileset dir="${jre-path}">
|
||||
<include name="**/*"/>
|
||||
</fileset>
|
||||
</copy>
|
||||
<exec executable="${ai-exe-path}">
|
||||
<arg line="/edit ${aip-path} /SetAppdir -buildname DefaultBuild -path [ProgramFilesFolder][ProductName]-${app.version}"/>
|
||||
</exec>
|
||||
@ -92,7 +100,7 @@
|
||||
<move file="${nbdist.dir}/installer_${app.name}_32-SetupFiles/installer_${app.name}_32.msi" tofile="${nbdist.dir}/${app.name}-${app.version}-32bit.msi" />
|
||||
</target>
|
||||
|
||||
<target name="run-ai-32" depends="add-ai-productinfo,add-ai-files,add-ai-jre,add-ai-shortcuts,add-ai-env,ai-build" description="Builds the 32 bit installer."/>
|
||||
<target name="run-ai-32" depends="add-ai-productinfo,add-ai-files,add-ai-shortcuts,add-ai-env,ai-build" description="Builds the 32 bit installer."/>
|
||||
|
||||
<target name="check-ai-64" if="jre.home.64" description="Builds the 64 bit installer IF JRE_HOME_64 is set.">
|
||||
<property environment="env"/>
|
||||
@ -102,6 +110,14 @@
|
||||
<var name="jre-path" value="${env.JRE_HOME_64}"/>
|
||||
<var name="package-type" value="x64" />
|
||||
<var name="jvm.max.mem" value="2048"/>
|
||||
<var name="new-jre-path" value="${inst-path}\jre"/>
|
||||
<delete failonerror="false" dir="${new-jre-path}"/>
|
||||
<mkdir dir="${new-jre-path}"/>
|
||||
<copy todir="${new-jre-path}" overwrite="true">
|
||||
<fileset dir="${jre-path}">
|
||||
<include name="**/*"/>
|
||||
</fileset>
|
||||
</copy>
|
||||
<echo message="aip-path: ${aip-path}" />
|
||||
<exec executable="${ai-exe-path}">
|
||||
<arg line="/edit ${aip-path} /SetAppdir -buildname DefaultBuild -path [ProgramFiles64Folder][ProductName]-${app.version}"/>
|
||||
@ -111,7 +127,7 @@
|
||||
<move file="${nbdist.dir}/installer_${app.name}_64-SetupFiles/installer_${app.name}_64.msi" tofile="${nbdist.dir}/${app.name}-${app.version}-64bit.msi" />
|
||||
</target>
|
||||
|
||||
<target name="run-ai-64" depends="add-ai-productinfo,add-ai-files,add-ai-jre,add-ai-shortcuts,ai-set-type,ai-build" description="Builds the 64 bit installer."/>
|
||||
<target name="run-ai-64" depends="add-ai-productinfo,add-ai-files,add-ai-shortcuts,ai-set-type,ai-build" description="Builds the 64 bit installer."/>
|
||||
|
||||
<target name="add-ai-productinfo" description="Add product information to the aip file">
|
||||
<scriptdef name="generateguid" language="javascript">
|
||||
@ -145,7 +161,7 @@
|
||||
<propertyfile file="${inst.property.file}">
|
||||
<!-- Note: can be higher on 64 bit systems, should be in sync with project.properties -->
|
||||
<entry key="default_options" value="@JVM_OPTIONS" />
|
||||
<entry key="jdkhome" value=""jre7"" />
|
||||
<entry key="jdkhome" value=""jre"" />
|
||||
</propertyfile>
|
||||
<!-- workaround for ant escaping : and = when setting properties -->
|
||||
<replace file="${inst.property.file}" token="@JVM_OPTIONS" value="${jvm.args}" />
|
||||
@ -181,14 +197,6 @@
|
||||
<available file="${theFile}" type="file" />
|
||||
</condition>
|
||||
</target>
|
||||
|
||||
<target name="add-ai-jre" description="Adds JRE to Advanced Installer project">
|
||||
<echo message="${ai-exe-path}" />
|
||||
<echo message="Adding JRE to installer: ${jre-path}"/>
|
||||
<exec executable="${ai-exe-path}">
|
||||
<arg line="/edit ${aip-path} /AddFolder APPDIR "${jre-path}"" />
|
||||
</exec>
|
||||
</target>
|
||||
|
||||
<target name="add-ai-shortcuts" description="Add shortcuts to the aip file">
|
||||
<echo message="Adding desktop/menu shortcuts..."/>
|
||||
|
@ -1,24 +1,36 @@
|
||||
/*! \page mod_report_page Developing Report Modules
|
||||
|
||||
\section report_summary Summary
|
||||
Report modules allow you to create different report types. Autopsy comes with moules to generate HTML and a body file for timeline creation. You can made additional modules to create custom output formats.
|
||||
Report modules allow you to create different report types. Autopsy comes with modules to generate HTML and Excel artifact reports, a tab delimited File report, and a body file for timeline creation. You can made additional modules to create custom output formats.
|
||||
|
||||
There are two types of reporting modules that differ in how the data is organized.
|
||||
There are three types of reporting modules that differ in how the data is organized.
|
||||
- General report modules are free form and you are allowed to organize the output however you want.
|
||||
- Table report modules organize the data into tables. If your output is in table format, this type of module will be easier to make the module because Autopsy does a lot of the organizing work for you.
|
||||
- File report modules are also table based, but they specifically deal with reporting on the Files in the case, not artifacts.
|
||||
|
||||
Each reporting submodule implements either the org.sleuthkit.autopsy.report.TableReportModule interface or the org.sleuthkit.autopsy.report.GeneralReportModule interface, and registers itself in layer.xml
|
||||
Each reporting submodule implements one of the org.sleuthkit.autopsy.report.TableReportModule interface, the org.sleuthkit.autopsy.report.GeneralReportModule interface, or the org.sleuthkit.autopsy.report.FileReportModule interface and registers itself in layer.xml
|
||||
|
||||
Implementing either of those interfaces will require the reporting module to implement a number of abstract methods. And depending on the type of report module, different methods will be invoked by the application.
|
||||
Implementing any of those interfaces will require the reporting module to implement a number of abstract methods. And depending on the type of report module, different methods will be invoked by the application.
|
||||
|
||||
Table report modules require their sub-classes to override methods to start and end tables, and add rows to those tables. These methods are provided data, generated from a default configuration panel, for the module to report on. Because of this, when creating a table report module one only needs to focus on how to display the data, not how to find it.
|
||||
|
||||
File report modules are similar to table report modules, but only require their sub-classes to start and end a single table, and add rows to that table. The methods are given an AbstractFile and a list of FileReportDataTypes, which specify what information about the file should be added to the report. The data can be extracted from the file by calling the FileReportDataTypes getValue method with the file as it's argument.
|
||||
|
||||
On the other hand, general report modules have a single method to generate the report. This method gives the module freedom to find and process any data it so chooses. General modules also have the ability to provide a configuration panel, allowing the user to choose from various displayed settings. The report module may then use the user's selection to generate a more specific report.
|
||||
|
||||
General modules are also given the responsibility of updating their report's progress bar and processing label in the UI. A progress panel is given to every general report module. It contains basic API to start, stop, and add to the progress bar, as well as update the processing label. The module is also expeted to check the progress bar's status occasionally to see if the user has manually canceled the report.
|
||||
General modules are also given the responsibility of updating their report's progress bar and processing label in the UI. A progress panel is given to every general report module. It contains basic API to start, stop, and add to the progress bar, as well as update the processing label. The module is also expected to check the progress bar's status occasionally to see if the user has manually canceled the report.
|
||||
|
||||
\section report_create_module Creating a Report Module
|
||||
To create a table report module, start off by creating a class and implementing either the TableReportModule interface or the GeneralReportModule interface.
|
||||
To create a table report module, start off by creating a class and implementing one of the TableReportModule interface, the FileReportModule interface, or the GeneralReportModule interface.
|
||||
|
||||
\section report_create_module_all All Report Modules
|
||||
All report modules will need to override the following methods:
|
||||
- org.sleuthkit.autopsy.report.ReportModule::getName()
|
||||
- org.sleuthkit.autopsy.report.ReportModule::getDescription()
|
||||
- org.sleuthkit.autopsy.report.ReportModule::getExtension()
|
||||
- org.sleuthkit.autopsy.report.ReportModule::getFilePath()
|
||||
|
||||
These will be called by Autopsy to set up the configuration panels and other information.
|
||||
|
||||
\subsection report_create_module_table Table Report Modules
|
||||
If you implement TableReportModule, you should override the methods:
|
||||
@ -35,7 +47,17 @@ If you implement TableReportModule, you should override the methods:
|
||||
- org.sleuthkit.autopsy.report.TableReportModule::addRow(List<String> row)
|
||||
- org.sleuthkit.autopsy.report.TableReportModule::dateToString(long date)
|
||||
|
||||
When generating table module reports, Autopsy will iterate through a list of user selected data, and call methods such as addRow(List<String> row) for every "row" of data it finds, or startTable(List<String> titles) for every new category it finds. Developers are guarenteed that every start of a data type, set, or table will be followed by an approptiate end. The focus for a table report module should be to take the given information and display it in a user friendly format. See org.sleuthkit.autopsy.report.ReportExcel for an example.
|
||||
When generating table module reports, Autopsy will iterate through a list of user selected data, and call methods such as addRow(List<String> row) for every "row" of data it finds, or startTable(List<String> titles) for every new category it finds. Developers are guaranteed that every start of a data type, set, or table will be followed by an appropriate end. The focus for a table report module should be to take the given information and display it in a user friendly format. See org.sleuthkit.autopsy.report.ReportExcel for an example.
|
||||
|
||||
\subsection report_create_module_file File Report Modules
|
||||
If you implement FileReportModule, the overriden methods will be:
|
||||
- org.sleuthkit.autopsy.report.FileReportModule::startReport(String path)
|
||||
- org.sleuthkit.autopsy.report.FileReportModule::endReport()
|
||||
- org.sleuthkit.autopsy.report.FileReportModule::startTable(List<FileReportDataTypes> headers)
|
||||
- org.sleuthkit.autopsy.report.FileReportModule::endTable()
|
||||
- org.sleuthkit.autopsy.report.FileReportModule::addRow(AbstractFile toAdd, List<FileReportDataTypes> columns)
|
||||
|
||||
As when generating table module reports, Autopsy will iterate through a list of user selected data (which are represented by FileReportDataTypes), and call addRow(AbstractFile toAdd, List<FileReportDataTypes> columns) for every abstract file in the case. Developers are guaranteed that the order of method calls will be startReport(), startTable(List<FileReportDataTypes> headers), addRow(AbstractFile toAdd, List<FileReportDataTypes> columns), AbstractFile toAdd, List<FileReportDataTypes> columns),..., endTable(), endReport().
|
||||
|
||||
\subsection report_create_module_general General Report Modules
|
||||
If you implement GeneralReportModule, the overriden methods will be:
|
||||
|
@ -4,7 +4,7 @@ app.title=Autopsy
|
||||
### lowercase version of above
|
||||
app.name=autopsy
|
||||
### if left unset, version will default to today's date
|
||||
app.version=3.0.7
|
||||
app.version=3.0.8
|
||||
### Build type isn't used at this point, but it may be useful
|
||||
### Must be one of: DEVELOPMENT, RELEASE
|
||||
build.type=RELEASE
|
||||
|
Loading…
x
Reference in New Issue
Block a user