1
0
mirror of https://github.com/elisspace/autopsy.git synced 2026-09-06 02:24:30 +00:00

Complete major functionality for external result imports and reports in Autopsy tree

This commit is contained in:
Richard Cordovano
2014-06-05 15:55:52 -04:00
parent a453b25f5c
commit 1be56087bc
13 changed files with 252 additions and 124 deletions

View File

@@ -1166,18 +1166,18 @@ public class Case implements SleuthkitCase.ErrorObserver {
public void receiveError(String context, String errorMessage) {
MessageNotifyUtil.Notify.error(context, errorMessage);
}
// RJCTODO: Clean this up
/**
* Inserts row into the reports table in the case database.
* @param [in] relPath The path of the report file, relative to the database (case directory in Autopsy).
* @param [in] displayName The display name for the new tag name.
* Adds a report to the case.
*
* @param [in] localPath The path of the report file, must be in the case directory or one of its subdirectories.
* @param [in] sourceModuleName The name of the module that created the report.
* @param [in] reportName The report name, may be empty.
* @return A Report data transfer object (DTO) for the new row.
* @throws TskCoreException
*/
public void addReport(String relPath, String displayName) throws TskCoreException {
Report report = this.db.addReport(relPath, displayName);
// RJCTODO: Fire event, perhaps with repoprt data
*/
public void addReport(String localPath, String srcModuleName, String reportName) throws TskCoreException {
Report report = this.db.addReport(localPath, srcModuleName, reportName);
Case.pcs.firePropertyChange(Events.REPORT_ADDED.toString(), null, report); // RJCTODO: Need exception firewall, maybe thread to do publishing
}

View File

@@ -209,9 +209,9 @@ RecentFilesNode.createSheet.name.name=Name
RecentFilesNode.createSheet.name.displayName=Name
RecentFilesNode.createSheet.name.desc=no description
RecentFilesNode.name.text=Recent Files
ReportNode.displayNameProperty.name=Display Name
ReportNode.displayNameProperty.displayName=Report Name
ReportNode.displayNameProperty.desc=Name of the report
ReportNode.sourceModuleNameProperty.name=Source Module Name
ReportNode.sourceModuleNameProperty.displayName=Source Module Name
ReportNode.sourceModuleNameProperty.desc=Name of the module that created the report
ReportNode.createdTimeProperty.name=Created Time
ReportNode.createdTimeProperty.displayName=Created Time
ReportNode.createdTimeProperty.desc=Time report was created

View File

@@ -18,11 +18,20 @@
*/
package org.sleuthkit.autopsy.datamodel;
import java.awt.Desktop;
import java.awt.event.ActionEvent;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.io.File;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.logging.Level;
import javax.swing.AbstractAction;
import javax.swing.Action;
import javax.swing.JOptionPane;
import org.openide.nodes.ChildFactory;
import org.openide.nodes.Children;
import org.openide.nodes.Node;
@@ -37,10 +46,10 @@ import org.sleuthkit.datamodel.TskCoreException;
/**
* Implements the Reports subtree of the Autopsy tree.
*/
public class Reports implements AutopsyVisitableItem {
public final class Reports implements AutopsyVisitableItem {
private static final SimpleDateFormat dateFormatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss z");
@Override
public <T> T accept(AutopsyItemVisitor<T> visitor) {
// The CreateAutopsyNodeVisitor constructs a ReportsListNode when it
@@ -51,7 +60,7 @@ public class Reports implements AutopsyVisitableItem {
/**
* The root node of the Reports subtree of the Autopsy tree.
*/
public static class ReportsListNode extends DisplayableItemNode {
public static final class ReportsListNode extends DisplayableItemNode {
private static final String DISPLAY_NAME = NbBundle.getMessage(ReportsListNode.class, "ReportsListNode.displayName");
private static final String ICON_PATH = "org/sleuthkit/autopsy/images/report_16.png"; //NON-NLS
@@ -82,7 +91,7 @@ public class Reports implements AutopsyVisitableItem {
* The child node factory that creates ReportNode children for a
* ReportsListNode.
*/
private static class ReportNodeFactory extends ChildFactory<Report> {
private static final class ReportNodeFactory extends ChildFactory<Report> {
ReportNodeFactory() {
Case.addPropertyChangeListener(new PropertyChangeListener() {
@@ -116,7 +125,7 @@ public class Reports implements AutopsyVisitableItem {
* A leaf node in the Reports subtree of the Autopsy tree, wraps a Report
* object.
*/
public static class ReportNode extends DisplayableItemNode {
public static final class ReportNode extends DisplayableItemNode {
private static final String ICON_PATH = "org/sleuthkit/autopsy/images/report_16.png"; //NON-NLS
private final Report report;
@@ -124,8 +133,8 @@ public class Reports implements AutopsyVisitableItem {
ReportNode(Report report) {
super(Children.LEAF, Lookups.fixed(report));
this.report = report;
super.setName(this.report.getDisplayName());
super.setDisplayName(this.report.getDisplayName());
super.setName(this.report.getSourceModuleName());
super.setDisplayName(this.report.getSourceModuleName());
this.setIconBaseWithExtension(ICON_PATH);
}
@@ -136,8 +145,8 @@ public class Reports implements AutopsyVisitableItem {
@Override
public <T> T accept(DisplayableItemNodeVisitor<T> visitor) {
// The GetPopupActionsDisplayableItemNodeVisitor gets the Actions for this class.
// The GetPreferredActionsDisplayableItemNodeVisitor RJCTODO
// The GetPopupActionsDisplayableItemNodeVisitor calls getActions(). // RJCTODO: Try to get rid of parent collapse all
// The GetPreferredActionsDisplayableItemNodeVisitor calls getPreferredAction().
// The IsLeafItemVisitor returns true.
// The ShowItemVisitor always returns true.
return visitor.visit(this);
@@ -151,19 +160,58 @@ public class Reports implements AutopsyVisitableItem {
propertiesSet = Sheet.createPropertiesSet();
sheet.put(propertiesSet);
}
propertiesSet.put(new NodeProperty<>(NbBundle.getMessage(this.getClass(), "ReportNode.displayNameProperty.name"),
NbBundle.getMessage(this.getClass(), "ReportNode.displayNameProperty.displayName"),
NbBundle.getMessage(this.getClass(), "ReportNode.displayNameProperty.desc"),
this.report.getDisplayName()));
propertiesSet.put(new NodeProperty<>(NbBundle.getMessage(this.getClass(), "ReportNode.sourceModuleNameProperty.name"),
NbBundle.getMessage(this.getClass(), "ReportNode.sourceModuleNameProperty.displayName"),
NbBundle.getMessage(this.getClass(), "ReportNode.sourceModuleNameProperty.desc"),
this.report.getSourceModuleName()));
propertiesSet.put(new NodeProperty<>(NbBundle.getMessage(this.getClass(), "ReportNode.createdTimeProperty.name"),
NbBundle.getMessage(this.getClass(), "ReportNode.createdTimeProperty.displayName"),
NbBundle.getMessage(this.getClass(), "ReportNode.createdTimeProperty.desc"),
dateFormatter.format(new java.util.Date(this.report.getCreatedTime() * 1000)).toString()));
dateFormatter.format(new java.util.Date(this.report.getCreatedTime() * 1000)).toString()));
propertiesSet.put(new NodeProperty<>(NbBundle.getMessage(this.getClass(), "ReportNode.pathProperty.name"),
NbBundle.getMessage(this.getClass(), "ReportNode.pathProperty.displayName"),
NbBundle.getMessage(this.getClass(), "ReportNode.pathProperty.desc"),
this.report.getPath()));
return sheet;
}
@Override
public Action[] getActions(boolean popup) {
List<Action> actions = new ArrayList<>();
actions.addAll(Arrays.asList(super.getActions(true)));
actions.add(new OpenReportAction());
return actions.toArray(new Action[actions.size()]);
}
@Override
public AbstractAction getPreferredAction() {
return new OpenReportAction();
}
private final class OpenReportAction extends AbstractAction { // RJCTODO: Needs name for menu
private OpenReportAction() {
super("Open Report"); // RJCTODO: bundle
}
@Override
public void actionPerformed(ActionEvent e) {
File file = new File(ReportNode.this.report.getPath());
try {
Desktop.getDesktop().open(file);
} catch (IOException ex) {
// RJCTODO: Failed to open no associated editor or associated application failed to launch
// RJCTODO: Bundle
JOptionPane.showMessageDialog(null, "There is no associated editor for reports of this type or the associated application failed to launch.",
"Open Report Failure", JOptionPane.ERROR_MESSAGE);
} catch (UnsupportedOperationException ex) {
// RJCTODO
} catch (IllegalArgumentException ex) {
// RJCTODO: File does not exist
} catch (SecurityException ex) {
// RJCTODO: permission denied
}
}
}
}
}

View File

@@ -66,6 +66,7 @@ import org.sleuthkit.autopsy.datamodel.RecentFilesFilterNode;
import org.sleuthkit.autopsy.datamodel.RecentFilesNode;
import org.sleuthkit.autopsy.datamodel.FileTypesNode;
import org.sleuthkit.autopsy.datamodel.KeywordHits;
import org.sleuthkit.autopsy.datamodel.Reports;
import org.sleuthkit.autopsy.datamodel.Tags;
import org.sleuthkit.datamodel.AbstractFile;
import org.sleuthkit.datamodel.BlackboardArtifact;
@@ -522,6 +523,11 @@ public class DataResultFilterNode extends FilterNode {
return openChild(khmln);
}
@Override
public AbstractAction visit(Reports.ReportNode reportNode) {
return reportNode.getPreferredAction();
}
@Override
protected AbstractAction defaultVisit(DisplayableItemNode c) {
return null;

View File

@@ -32,8 +32,6 @@ package org.sleuthkit.autopsy.examples;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.List;
import java.util.logging.Level;
@@ -56,6 +54,7 @@ import org.sleuthkit.autopsy.externalresults.ExternalResultsXMLParser;
import org.sleuthkit.autopsy.ingest.DataSourceIngestModule;
import org.sleuthkit.autopsy.ingest.DataSourceIngestModuleProgress;
import org.sleuthkit.autopsy.ingest.IngestJobContext;
import org.sleuthkit.autopsy.ingest.IngestMessage;
import org.sleuthkit.autopsy.ingest.IngestModuleReferenceCounter;
import org.sleuthkit.autopsy.ingest.IngestServices;
import org.sleuthkit.datamodel.BlackboardArtifact.ARTIFACT_TYPE;
@@ -126,7 +125,9 @@ public class SampleExecutableDataSourceIngestModule implements DataSourceIngestM
List<ErrorInfo> errors = resultsParser.getErrorInfo();
ExternalResultsImporter importer = new ExternalResultsImporter();
errors.addAll(importer.importResults(results));
// RJCTODO: Report error messages to UI
for (ErrorInfo errorInfo : errors) {
IngestServices.getInstance().postMessage(IngestMessage.createErrorMessage(moduleName, "External Results Import Error", errorInfo.getMessage()));
}
progressBar.progress(2);
} catch (TskCoreException | InterruptedException | ParserConfigurationException | TransformerException | IOException ex) {
Logger logger = IngestServices.getInstance().getLogger(moduleName);
@@ -139,8 +140,8 @@ public class SampleExecutableDataSourceIngestModule implements DataSourceIngestM
private void generateSimulatedResults(String resultsFilePath) throws ParserConfigurationException, IOException, TransformerConfigurationException, TransformerException {
List<String> derivedFilePaths = generateSimulatedDerivedFiles();
String reportFilePath = generateSimulatedReport();
generateSimulatedResultsFile(derivedFilePaths, reportFilePath, resultsFilePath);
List<String> reportFilePaths = generateSimulatedReports();
generateSimulatedResultsFile(derivedFilePaths, reportFilePaths, resultsFilePath);
}
private List<String> generateSimulatedDerivedFiles() throws IOException {
@@ -156,10 +157,14 @@ public class SampleExecutableDataSourceIngestModule implements DataSourceIngestM
return filePaths;
}
private String generateSimulatedReport() throws IOException {
String reportFileName = String.format("job_%d_report.txt", jobId);
String reportContents = "This is a simulated report.";
return generateFile(reportFileName, reportContents.getBytes());
private List<String> generateSimulatedReports() throws IOException {
List<String> filePaths = new ArrayList<>();
String fileContents = "This is a simulated report.";
for (int i = 0; i < 2; ++i) {
String fileName = String.format("job_%d_report_%d.txt", jobId, i);
filePaths.add(generateFile(fileName, fileContents.getBytes()));
}
return filePaths;
}
private String generateFile(String fileName, byte[] fileContents) throws IOException {
@@ -175,7 +180,58 @@ public class SampleExecutableDataSourceIngestModule implements DataSourceIngestM
return filePath;
}
private void generateSimulatedResultsFile(List<String> derivedFilePaths, String reportPath, String resultsFilePath) throws ParserConfigurationException, TransformerConfigurationException, TransformerException {
private void generateSimulatedResultsFile(List<String> derivedFilePaths, List<String> reportPaths, String resultsFilePath) throws ParserConfigurationException, TransformerConfigurationException, TransformerException {
// SAMPLE GENERATED BY THE CODE BELOW:
//
// <?xml version="1.0" encoding="UTF-8" standalone="no"?>
// <autopsy_results>
// <derived_files>
// <derived_file>
// <local_path>C:\cases\Small\ModuleOutput\Sample Executable Ingest Module\job_1_derived_file_0.txt</local_path>
// <parent_file>/WINDOWS/system32/ntmsapi.dll</parent_file>
// </derived_file>
// <derived_file>
// <local_path>C:\cases\Small\ModuleOutput\Sample Executable Ingest Module\job_1_derived_file_1.txt</local_path>
// <parent_file>/WINDOWS/system32/ntmsapi.dll/job_1_derived_file_0.txt</parent_file>
// </derived_file>
// </derived_files>
// <artifacts>
// <artifact type="TSK_INTERESTING_FILE_HIT">
// <source_file>/WINDOWS/system32/ntmsapi.dll</source_file>
// <attribute type="TSK_SET_NAME">
// <value>SampleInterestingFilesSet</value>
// <source_module>Sample Executable Ingest Module</source_module>
// </attribute>
// </artifact>
// <artifact type="SampleArtifactType">
// <source_file>/WINDOWS/system32/ntmsapi.dll/job_1_derived_file_0.txt</source_file>
// <attribute type="SampleArtifactAttributeType">
// <value type="text">One</value>
// </attribute>
// <attribute type="SampleArtifactAttributeType">
// <value type="int32">2</value>
// </attribute>
// <attribute type="SampleArtifactAttributeType">
// <value type="int64">3</value>
// </attribute>
// <attribute type="SampleArtifactAttributeType">
// <value type="double">4.0</value>
// </attribute>
// </artifact>
// </artifacts>
// <reports>
// <report>
// <local_path>C:\cases\Small\ModuleOutput\Sample Executable Ingest Module\job_1_report_0.txt</local_path>
// <source_module>Sample Executable Ingest Module</source_module>
// <report_name>Sample Report</report_name>
// </report>
// <report>
// <local_path>C:\cases\Small\ModuleOutput\Sample Executable Ingest Module\job_1_report_1.txt</local_path>
// <source_module>Sample Executable Ingest Module</source_module>
// </report>
// </reports>
// </autopsy_results>
// Create the XML DOM document and the root element.
DocumentBuilderFactory docBuilderFactory = DocumentBuilderFactory.newInstance();
DocumentBuilder docBuilder = docBuilderFactory.newDocumentBuilder();
@@ -190,8 +246,10 @@ public class SampleExecutableDataSourceIngestModule implements DataSourceIngestM
// Add derived file elements to the derived files list element. Each
// file element gets required local path and parent file child elements.
// Note that the local path of the derived file must be to a location in
// a subdirectory of the case directory and the parent file must be
// specified using the path format used in the case database.
// the case directory or a subdirectory of the case directory and the
// parent file must be specified using the path format used in the case
// database, e.g., /WINDOWS/system32/ntmsapi.dll, where volume, file
// system, etc. are not in the path.
for (int i = 0; i < derivedFilePaths.size(); ++i) {
String filePath = derivedFilePaths.get(i);
Element derivedFileElement = doc.createElement(ExternalResultsXMLParser.TagNames.DERIVED_FILE_ELEM.toString());
@@ -288,21 +346,29 @@ public class SampleExecutableDataSourceIngestModule implements DataSourceIngestM
Element reportsListElement = doc.createElement(ExternalResultsXMLParser.TagNames.REPORTS_LIST_ELEM.toString());
rootElement.appendChild(reportsListElement);
// Add a report element to the reports list element.
Element reportElement = doc.createElement(ExternalResultsXMLParser.TagNames.REPORT_ELEM.toString());
reportsListElement.appendChild(reportElement);
// Add the required display name element to the report element.
Element reportDisplayNameElement = doc.createElement(ExternalResultsXMLParser.TagNames.DISPLAY_NAME_ELEM.toString());
reportDisplayNameElement.setTextContent("Sample Report");
reportElement.appendChild(reportDisplayNameElement);
// Add the required local path element to the report element. Note that
// the local path must be an absolute path to a location in a
// subdirectory of the case direcotry.
Element reportPathElement = doc.createElement(ExternalResultsXMLParser.TagNames.LOCAL_PATH_ELEM.toString());
reportPathElement.setTextContent(reportPath);
reportElement.appendChild(reportPathElement);
// Add report elements to the reports list element. Each report element
// gets required local path and source module child elements. There is
// also an optional report name element. Note that the local path of the
// report must be to a location in the case directory or a subdirectory
// of the case directory and the parent file must be specified using the
// path format used in the case database, e.g., /WINDOWS/system32/ntmsapi.dll,
// where volume, file system, etc. are not in the path.
for (int i = 0; i < reportPaths.size(); ++i) {
String reportPath = reportPaths.get(i);
Element reportElement = doc.createElement(ExternalResultsXMLParser.TagNames.REPORT_ELEM.toString());
reportsListElement.appendChild(reportElement);
Element reportPathElement = doc.createElement(ExternalResultsXMLParser.TagNames.LOCAL_PATH_ELEM.toString());
reportPathElement.setTextContent(reportPath);
reportElement.appendChild(reportPathElement);
Element reportSourceModuleElement = doc.createElement(ExternalResultsXMLParser.TagNames.SOURCE_MODULE_ELEM.toString());
reportSourceModuleElement.setTextContent(moduleName);
reportElement.appendChild(reportSourceModuleElement);
if (i == 0) {
Element reportNameElement = doc.createElement(ExternalResultsXMLParser.TagNames.REPORT_NAME_ELEM.toString());
reportNameElement.setTextContent("Sample Report");
reportElement.appendChild(reportNameElement);
}
}
TransformerFactory transformerFactory = TransformerFactory.newInstance();
Transformer transformer = transformerFactory.newTransformer();

View File

@@ -79,21 +79,18 @@ class SampleFileIngestModule implements FileIngestModule {
// modules.
Case autopsyCase = Case.getCurrentCase();
SleuthkitCase sleuthkitCase = autopsyCase.getSleuthkitCase();
// See if the attribute type has already been defined.
try {
// See if the attribute type has already been defined.
attrId = sleuthkitCase.getAttrTypeID("ATTR_SAMPLE");
} catch (TskCoreException e) {
// If not, create the the attribute type.
try {
if (attrId == -1) {
attrId = sleuthkitCase.addAttrType("ATTR_SAMPLE", "Sample Attribute");
} catch (TskCoreException ex) {
IngestServices ingestServices = IngestServices.getInstance();
Logger logger = ingestServices.getLogger(SampleIngestModuleFactory.getModuleName());
logger.log(Level.SEVERE, "Failed to create blackboard attribute", ex);
attrId = -1;
throw new IngestModuleException(ex.getLocalizedMessage());
}
} catch (TskCoreException ex) {
IngestServices ingestServices = IngestServices.getInstance();
Logger logger = ingestServices.getLogger(SampleIngestModuleFactory.getModuleName());
logger.log(Level.SEVERE, "Failed to create blackboard attribute", ex);
attrId = -1;
throw new IngestModuleException(ex.getLocalizedMessage());
}
}
}

View File

@@ -57,14 +57,14 @@ final public class ExternalResults {
return Collections.unmodifiableList(artifacts);
}
void addReport(String displayName, String localPath) {
if (displayName.isEmpty()) {
throw new IllegalArgumentException("displayName argument is empty");
}
void addReport(String localPath, String sourceModuleName, String reportName) {
if (localPath.isEmpty()) {
throw new IllegalArgumentException("localPath argument is empty");
}
Report report = new Report(displayName, localPath);
if (sourceModuleName.isEmpty()) {
throw new IllegalArgumentException("sourceModuleName argument is empty");
}
Report report = new Report(localPath, sourceModuleName, reportName);
reports.add(report);
}
@@ -157,21 +157,27 @@ final public class ExternalResults {
static final class Report {
private final String displayName;
private final String localPath;
private final String sourceModuleName;
private final String reportName;
Report(String displayName, String localPath) {
this.displayName = displayName;
Report(String localPath, String sourceModuleName, String displayName) {
this.localPath = localPath;
}
String getDisplayName() {
return displayName;
this.sourceModuleName = sourceModuleName;
this.reportName = displayName;
}
String getLocalPath() {
return localPath;
}
String getSourceModuleName() {
return sourceModuleName;
}
String getReportName() {
return reportName;
}
}
static final class DerivedFile {

View File

@@ -23,7 +23,6 @@ import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.logging.Level;
import org.sleuthkit.autopsy.casemodule.Case;
@@ -65,7 +64,9 @@ public final class ExternalResultsImporter {
importDerivedFiles(results);
importArtifacts(results);
importReports(results);
return Collections.unmodifiableList(this.errors);
List<ErrorInfo> importErrors = new ArrayList(this.errors);
this.errors.clear();
return importErrors;
}
private void importDerivedFiles(ExternalResults results) {
@@ -78,7 +79,7 @@ public final class ExternalResultsImporter {
String relativePath = this.getPathRelativeToCaseFolder(localPath);
if (!relativePath.isEmpty()) {
String parentFilePath = fileData.getParentPath();
AbstractFile parentFile = findFileInCaseDatabase(results.getDataSource(), parentFilePath);
AbstractFile parentFile = findFileInCaseDatabase(parentFilePath);
if (parentFile != null) {
DerivedFile derivedFile = fileManager.addDerivedFile(localFile.getName(), relativePath, localFile.length(),
0, 0, 0, 0, // Do not currently have file times for derived files from external processes.
@@ -110,19 +111,19 @@ public final class ExternalResultsImporter {
try {
// Add the artifact to the case database.
boolean artifactTypeIsUserDefined = false;
int artifactTypeId = caseDb.getArtifactTypeIdIfExists(artifactData.getType());
int artifactTypeId = caseDb.getArtifactTypeID(artifactData.getType());
if (artifactTypeId == -1) {
artifactTypeId = caseDb.addArtifactType(artifactData.getType(), artifactData.getType());
artifactTypeIsUserDefined = true;
}
Content sourceFile = findFileInCaseDatabase(results.getDataSource(), artifactData.getSourceFilePath());
Content sourceFile = findFileInCaseDatabase(artifactData.getSourceFilePath());
if (sourceFile != null) {
BlackboardArtifact artifact = sourceFile.newArtifact(artifactTypeId);
// Add the artifact's attributes to the case database.
Collection<BlackboardAttribute> attributes = new ArrayList<>();
for (ExternalResults.ArtifactAttribute attributeData : artifactData.getAttributes()) {
int attributeTypeId = caseDb.getAttrTypeIdIfExists(attributeData.getType());
int attributeTypeId = caseDb.getAttrTypeID(attributeData.getType());
if (attributeTypeId == -1) {
attributeTypeId = caseDb.addAttrType(attributeData.getType(), attributeData.getType());
}
@@ -157,6 +158,10 @@ public final class ExternalResultsImporter {
if (!artifactTypeIsUserDefined) {
IngestServices.getInstance().fireModuleDataEvent(new ModuleDataEvent(this.getClass().getSimpleName(), BlackboardArtifact.ARTIFACT_TYPE.fromID(artifactTypeId)));
}
} else {
String errorMessage = String.format("Could not import %s artifact from %s, source file not found", artifactData.getType(), artifactData.getSourceFilePath());
ExternalResultsImporter.logger.log(Level.SEVERE, errorMessage);
this.errors.add(new ErrorInfo(ExternalResultsImporter.class.getName(), errorMessage));
}
} catch (TskCoreException ex) {
String errorMessage = String.format("Could not import %s artifact from %s, error updating case database", artifactData.getType(), artifactData.getSourceFilePath());
@@ -172,10 +177,7 @@ public final class ExternalResultsImporter {
try {
File reportFile = new File(reportPath);
if (reportFile.exists()) {
String relativePath = this.getPathRelativeToCaseFolder(reportPath);
if (!relativePath.isEmpty()) {
Case.getCurrentCase().addReport(relativePath, report.getDisplayName());
}
Case.getCurrentCase().addReport(reportPath, report.getSourceModuleName(), report.getReportName());
} else {
String errorMessage = String.format("Could not import report at %s, file does not exist", reportPath);
ExternalResultsImporter.logger.log(Level.SEVERE, errorMessage);
@@ -189,7 +191,7 @@ public final class ExternalResultsImporter {
}
}
private AbstractFile findFileInCaseDatabase(Content dataSource, String filePath) throws TskCoreException {
private AbstractFile findFileInCaseDatabase(String filePath) throws TskCoreException {
AbstractFile file = null;
// Split the path into the file name and the parent path.
String fileName = filePath;
@@ -203,10 +205,9 @@ public final class ExternalResultsImporter {
String condition = "name='" + fileName + "' AND parent_path='" + parentPath + "'"; //NON-NLS
List<AbstractFile> files = Case.getCurrentCase().getSleuthkitCase().findAllFilesWhere(condition);
if (!files.isEmpty()) {
if (files.size() == 1) {
file = files.get(0);
} else {
String errorMessage = String.format("Parent file path %s is ambiguous", filePath);
file = files.get(0);
if (files.size() > 1) {
String errorMessage = String.format("Parent file path %s is ambiguous, using first file found", filePath);
this.recordError(errorMessage);
}
}

View File

@@ -19,7 +19,6 @@
package org.sleuthkit.autopsy.externalresults;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
@@ -61,7 +60,7 @@ public final class ExternalResultsXMLParser implements ExternalResultsParser {
SOURCE_MODULE_ELEM("source_module"), //NON-NLS
REPORTS_LIST_ELEM("reports"), //NON-NLS
REPORT_ELEM("report"), //NON-NLS
DISPLAY_NAME_ELEM("display_name"); //NON-NLS
REPORT_NAME_ELEM("report_name"); //NON-NLS
private final String text;
private TagNames(final String text) {
@@ -154,7 +153,7 @@ public final class ExternalResultsXMLParser implements ExternalResultsParser {
@Override
public List<ErrorInfo> getErrorInfo() {
return Collections.unmodifiableList(this.errors);
return new ArrayList<>(this.errors);
}
private void parseDerivedFiles(Element rootElement) {
@@ -266,17 +265,19 @@ public final class ExternalResultsXMLParser implements ExternalResultsParser {
NodeList reportNodes = reportsListElem.getElementsByTagName(TagNames.REPORT_ELEM.toString());
for (int j = 0; j < reportNodes.getLength(); ++j) {
Element reportElem = (Element) reportNodes.item(j);
// Get the display name.
String displayName = getChildElementContent(reportElem, TagNames.DISPLAY_NAME_ELEM.toString(), true);
if (displayName.isEmpty()) {
continue;
}
// Get the local path.
String path = getChildElementContent(reportElem, TagNames.LOCAL_PATH_ELEM.toString(), true);
if (path.isEmpty()) {
continue;
}
this.resultsData.addReport(displayName, path);
// Get the source module.
String sourceModule = getChildElementContent(reportElem, TagNames.SOURCE_MODULE_ELEM.toString(), true);
if (path.isEmpty()) {
continue;
}
// Get the optional report name.
String reportName = getChildElementContent(reportElem, TagNames.REPORT_NAME_ELEM.toString(), false);
this.resultsData.addReport(path, sourceModule, reportName);
}
}
}

View File

@@ -2,7 +2,7 @@
*
* Autopsy Forensic Browser
*
* Copyright 2012 Basis Technology Corp.
* Copyright 2012-2014 Basis Technology Corp.
*
* Copyright 2012 42six Solutions.
* Contact: aebadirad <at> 42six <dot> com
@@ -25,8 +25,6 @@ package org.sleuthkit.autopsy.report;
import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.IOException;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.List;
import java.util.logging.Level;
import javax.swing.JPanel;
@@ -151,11 +149,17 @@ import org.sleuthkit.datamodel.*;
logger.log(Level.WARNING, "Could not write the temp body file report.", ex); //NON-NLS
} finally {
try {
out.flush();
out.close();
if (out != null) {
out.flush();
out.close();
Case.getCurrentCase().addReport(reportPath, "TSK Body File", "");
}
} catch (IOException ex) {
logger.log(Level.WARNING, "Could not flush and close the BufferedWriter.", ex); //NON-NLS
}
} catch (TskCoreException ex) {
String errorMessage = String.format("Error adding %s to case as a report", reportPath); //NON-NLS
logger.log(Level.SEVERE, errorMessage, ex);
}
}
progressPanel.complete();
} catch(TskCoreException ex) {

View File

@@ -1,7 +1,7 @@
/*
* Autopsy Forensic Browser
*
* Copyright 2013 Basis Technology Corp.
* Copyright 2013-2014 Basis Technology Corp.
* Contact: carrier <at> sleuthkit <dot> org
*
* Licensed under the Apache License, Version 2.0 (the "License");
@@ -26,9 +26,11 @@ import java.util.logging.Level;
import org.apache.poi.hssf.util.HSSFColor;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.openide.util.Exceptions;
import org.openide.util.NbBundle;
import org.sleuthkit.autopsy.casemodule.Case;
import org.sleuthkit.autopsy.coreutils.Logger;
import org.sleuthkit.datamodel.TskCoreException;
class ReportExcel implements TableReportModule {
private static final Logger logger = Logger.getLogger(ReportExcel.class.getName());
@@ -110,8 +112,12 @@ import org.sleuthkit.autopsy.coreutils.Logger;
try {
out = new FileOutputStream(reportPath);
wb.write(out);
Case.getCurrentCase().addReport(reportPath, "Excel Report", "");
} catch (IOException ex) {
logger.log(Level.SEVERE, "Failed to write Excel report.", ex); //NON-NLS
} catch (TskCoreException ex) {
String errorMessage = String.format("Error adding %s to case as a report", reportPath); //NON-NLS
logger.log(Level.SEVERE, errorMessage, ex);
} finally {
if (out != null) {
try {

View File

@@ -2,7 +2,7 @@
*
* Autopsy Forensic Browser
*
* Copyright 2012 Basis Technology Corp.
* Copyright 2012-2014 Basis Technology Corp.
*
* Copyright 2012 42six Solutions.
* Contact: aebadirad <at> 42six <dot> com
@@ -803,8 +803,9 @@ import org.sleuthkit.datamodel.TskData.TSK_DB_FILES_TYPE_ENUM;
*/
private void writeIndex() {
Writer indexOut = null;
String indexFilePath = path + "index.html";
try {
indexOut = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(path + "index.html"), "UTF-8")); //NON-NLS
indexOut = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(indexFilePath), "UTF-8")); //NON-NLS
StringBuilder index = new StringBuilder();
index.append("<head>\n<title>").append( //NON-NLS
NbBundle.getMessage(this.getClass(), "ReportHTML.writeIndex.title", currentCase.getName())).append(
@@ -820,22 +821,12 @@ import org.sleuthkit.datamodel.TskData.TSK_DB_FILES_TYPE_ENUM;
index.append("</frameset>\n"); //NON-NLS
index.append("</html>"); //NON-NLS
indexOut.write(index.toString());
// RJCTODO: Add this file as a report, clean this up, make utility
String relativePath = "";
Path pathObj = Paths.get(path + "index.html");
Path pathBase = Paths.get(Case.getCurrentCase().getCaseDirectory());
try {
Path pathRelative = pathBase.relativize(pathObj);
relativePath = pathRelative.toString();
} catch (IllegalArgumentException ex) {
// RJCTODO
}
Case.getCurrentCase().addReport("HTML Report", relativePath);
Case.getCurrentCase().addReport(indexFilePath, "HTML Report", "");
} catch (IOException ex) {
logger.log(Level.SEVERE, "Error creating Writer for index.html: {0}", ex); //NON-NLS
} catch (TskCoreException ex) {
Exceptions.printStackTrace(ex); // RJCTODO: Handle this
String errorMessage = String.format("Error adding %s to case as a report", indexFilePath); //NON-NLS
logger.log(Level.SEVERE, errorMessage, ex);
} finally {
try {
if(indexOut != null) {

View File

@@ -256,11 +256,13 @@ class ReportKML implements GeneralReportModule {
FileOutputStream writer = new FileOutputStream(reportPath);
outputter.output(kmlDocument, writer);
writer.close();
Case.getCurrentCase().addReport(reportPath, "KML Report", "");
} catch (IOException ex) {
logger.log(Level.WARNING, "Could not write the KML file.", ex); //NON-NLS
} catch (TskCoreException ex) {
String errorMessage = String.format("Error adding %s to case as a report", reportPath); //NON-NLS
logger.log(Level.SEVERE, errorMessage, ex);
}
} catch (IOException ex) {
logger.log(Level.WARNING, "Could not write the KML report.", ex); //NON-NLS
}