mirror of
https://github.com/overcuriousity/autopsy-flatpak.git
synced 2025-07-17 10:17:41 +00:00
fixed reporting bugs, detect thumbnail images by blackboard
This commit is contained in:
parent
ad47937145
commit
17011d3031
@ -27,15 +27,19 @@ import java.awt.image.BufferedImage;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.logging.Level;
|
||||
import javax.imageio.ImageIO;
|
||||
import javax.swing.ImageIcon;
|
||||
import org.openide.util.Exceptions;
|
||||
import org.sleuthkit.autopsy.casemodule.Case;
|
||||
import org.sleuthkit.autopsy.contentviewers.Utilities;
|
||||
import org.sleuthkit.autopsy.corelibs.ScalrWrapper;
|
||||
import org.sleuthkit.datamodel.AbstractFile;
|
||||
import org.sleuthkit.datamodel.BlackboardArtifact;
|
||||
import org.sleuthkit.datamodel.BlackboardAttribute;
|
||||
import org.sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE;
|
||||
import org.sleuthkit.datamodel.Content;
|
||||
import org.sleuthkit.datamodel.ReadContentInputStream;
|
||||
import org.sleuthkit.datamodel.TskCoreException;
|
||||
@ -51,7 +55,7 @@ public class ImageUtils {
|
||||
private static final Logger logger = Logger.getLogger(ImageUtils.class.getName());
|
||||
private static final Image DEFAULT_ICON = new ImageIcon("/org/sleuthkit/autopsy/images/file-icon.png").getImage();
|
||||
private static final List<String> SUPP_EXTENSIONS = Arrays.asList(ImageIO.getReaderFileSuffixes());
|
||||
|
||||
private static final List<String> SUPP_MIME_TYPES = Arrays.asList(ImageIO.getReaderMIMETypes());
|
||||
/**
|
||||
* Get the default Icon, which is the icon for a file.
|
||||
* @return
|
||||
@ -72,18 +76,41 @@ public class ImageUtils {
|
||||
}
|
||||
|
||||
AbstractFile f = (AbstractFile) content;
|
||||
final String fName = f.getName();
|
||||
final int dotIdx = fName.lastIndexOf('.');
|
||||
if (dotIdx == -1 || dotIdx == (fName.length() - 1)) {
|
||||
return isJpegFileHeader(f);
|
||||
if (f.getSize() == 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
final String ext = fName.substring(dotIdx + 1).toLowerCase();
|
||||
// check the blackboard for a file type attribute
|
||||
try {
|
||||
ArrayList <BlackboardAttribute> attributes = f.getGenInfoAttributes(ATTRIBUTE_TYPE.TSK_FILE_TYPE_SIG);
|
||||
for (BlackboardAttribute attribute : attributes) {
|
||||
if (SUPP_MIME_TYPES.contains(attribute.getValueString())) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (TskCoreException ex) {
|
||||
logger.log(Level.WARNING, "Error while getting file signature from blackboard.", ex);
|
||||
}
|
||||
|
||||
final String fName = f.getName();
|
||||
final int dotIdx = fName.lastIndexOf('.');
|
||||
|
||||
// if we have an extension, check it
|
||||
if ((dotIdx != -1) && (dotIdx != (fName.length() - 1))) {
|
||||
|
||||
final String ext = fName.substring(dotIdx + 1).toLowerCase();
|
||||
|
||||
// Note: thumbnail generator only supports JPG, GIF, and PNG for now
|
||||
return (f.getSize() > 0
|
||||
&& SUPP_EXTENSIONS.contains(ext));
|
||||
// Note: thumbnail generator only supports JPG, GIF, and PNG for now
|
||||
if (SUPP_EXTENSIONS.contains(ext)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
// if no extension or one that is not for an image, then read the content
|
||||
return isJpegFileHeader(f);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get an icon of a specified size.
|
||||
|
@ -383,12 +383,19 @@ public class ReportGenerator {
|
||||
progress.setMaximumProgress(ARTIFACT_TYPE.values().length + 2); // +2 for content and blackboard artifact tags
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
// report on the blackboard results
|
||||
makeBlackboardArtifactTables();
|
||||
|
||||
// report on the tagged files and artifacts
|
||||
makeContentTagsTables();
|
||||
makeBlackboardArtifactTagsTables();
|
||||
|
||||
// report on the tagged images
|
||||
makeThumbnailTable();
|
||||
|
||||
// finish progress, wrap up
|
||||
for (TableReportModule module : tableModules) {
|
||||
tableProgress.get(module).complete();
|
||||
module.endReport();
|
||||
@ -397,11 +404,14 @@ public class ReportGenerator {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate the tables for the selected blackboard artifacts
|
||||
*/
|
||||
private void makeBlackboardArtifactTables() {
|
||||
// Make a comment string describing the tag names filter in effect.
|
||||
StringBuilder comment = new StringBuilder();
|
||||
if (!tagNamesFilter.isEmpty()) {
|
||||
comment.append("This report only includes results tagged with: ");
|
||||
comment.append("Contains results that were tagged with one of the following: ");
|
||||
comment.append(makeCommaSeparatedList(tagNamesFilter));
|
||||
}
|
||||
|
||||
@ -483,6 +493,9 @@ public class ReportGenerator {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Make table for tagged files
|
||||
*/
|
||||
private void makeContentTagsTables() {
|
||||
// Check for cancellaton.
|
||||
removeCancelledTableReportModules();
|
||||
@ -508,7 +521,7 @@ public class ReportGenerator {
|
||||
ArrayList<String> columnHeaders = new ArrayList<>(Arrays.asList("File", "Tag", "Comment"));
|
||||
StringBuilder comment = new StringBuilder();
|
||||
if (!tagNamesFilter.isEmpty()) {
|
||||
comment.append("This report only includes file tagged with: ");
|
||||
comment.append("Contains files that were tagged with one of the following: ");
|
||||
comment.append(makeCommaSeparatedList(tagNamesFilter));
|
||||
}
|
||||
if (module instanceof ReportHTML) {
|
||||
@ -524,20 +537,25 @@ public class ReportGenerator {
|
||||
|
||||
// Give the modules the rows for the content tags.
|
||||
for (ContentTag tag : tags) {
|
||||
if (passesTagNamesFilter(tag.getName().getDisplayName())) {
|
||||
checkIfTagHasImage(tag);
|
||||
ArrayList<String> rowData = new ArrayList<>(Arrays.asList(tag.getContent().getName(), tag.getName().getDisplayName(), tag.getComment()));
|
||||
for (TableReportModule module : tableModules) {
|
||||
// @@@ This casting is a tricky little workaround to allow the HTML report module to slip in a content hyperlink.
|
||||
if (module instanceof ReportHTML) {
|
||||
ReportHTML htmlReportModule = (ReportHTML)module;
|
||||
htmlReportModule.addRowWithTaggedContentHyperlink(rowData, tag);
|
||||
}
|
||||
else {
|
||||
module.addRow(rowData);
|
||||
}
|
||||
}
|
||||
// skip tags that we are not reporting on
|
||||
if (passesTagNamesFilter(tag.getName().getDisplayName()) == false) {
|
||||
continue;
|
||||
}
|
||||
|
||||
ArrayList<String> rowData = new ArrayList<>(Arrays.asList(tag.getContent().getName(), tag.getName().getDisplayName(), tag.getComment()));
|
||||
for (TableReportModule module : tableModules) {
|
||||
// @@@ This casting is a tricky little workaround to allow the HTML report module to slip in a content hyperlink.
|
||||
if (module instanceof ReportHTML) {
|
||||
ReportHTML htmlReportModule = (ReportHTML)module;
|
||||
htmlReportModule.addRowWithTaggedContentHyperlink(rowData, tag);
|
||||
}
|
||||
else {
|
||||
module.addRow(rowData);
|
||||
}
|
||||
}
|
||||
|
||||
// see if it is for an image so that we later report on it
|
||||
checkIfTagHasImage(tag);
|
||||
}
|
||||
|
||||
// The the modules content tags reporting is ended.
|
||||
@ -548,6 +566,9 @@ public class ReportGenerator {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate the tables for the tagged artifacts
|
||||
*/
|
||||
private void makeBlackboardArtifactTagsTables() {
|
||||
// Check for cancellaton.
|
||||
removeCancelledTableReportModules();
|
||||
@ -579,14 +600,18 @@ public class ReportGenerator {
|
||||
|
||||
// Give the modules the rows for the content tags.
|
||||
for (BlackboardArtifactTag tag : tags) {
|
||||
if (passesTagNamesFilter(tag.getName().getDisplayName())) {
|
||||
checkIfTagHasImage(tag);
|
||||
List<String> row;
|
||||
for (TableReportModule module : tableModules) {
|
||||
row = new ArrayList<>(Arrays.asList(tag.getArtifact().getArtifactTypeName(), tag.getName().getDisplayName(), tag.getComment(), tag.getContent().getName()));
|
||||
module.addRow(row);
|
||||
}
|
||||
if (passesTagNamesFilter(tag.getName().getDisplayName()) == false) {
|
||||
continue;
|
||||
}
|
||||
|
||||
List<String> row;
|
||||
for (TableReportModule module : tableModules) {
|
||||
row = new ArrayList<>(Arrays.asList(tag.getArtifact().getArtifactTypeName(), tag.getName().getDisplayName(), tag.getComment(), tag.getContent().getName()));
|
||||
module.addRow(row);
|
||||
}
|
||||
|
||||
// check if the tag is an image that we should later make a thumbnail for
|
||||
checkIfTagHasImage(tag);
|
||||
}
|
||||
|
||||
// The the modules blackboard artifact tags reporting is ended.
|
||||
@ -597,7 +622,12 @@ public class ReportGenerator {
|
||||
}
|
||||
}
|
||||
|
||||
boolean passesTagNamesFilter(String tagName) {
|
||||
/**
|
||||
* Test if the user requested that this tag be reported on
|
||||
* @param tagName
|
||||
* @return true if it should be reported on
|
||||
*/
|
||||
private boolean passesTagNamesFilter(String tagName) {
|
||||
return tagNamesFilter.isEmpty() || tagNamesFilter.contains(tagName);
|
||||
}
|
||||
|
||||
@ -611,25 +641,36 @@ public class ReportGenerator {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Make a report for the files that were previously found to
|
||||
* be images.
|
||||
*/
|
||||
private void makeThumbnailTable() {
|
||||
for (TableReportModule module : tableModules) {
|
||||
tableProgress.get(module).updateStatusLabel("Now processing Tagged Images...");
|
||||
tableProgress.get(module).updateStatusLabel("Creating thumbnails...");
|
||||
|
||||
if (module instanceof ReportHTML) {
|
||||
ReportHTML htmlModule = (ReportHTML) module;
|
||||
htmlModule.startDataType("Tagged Images", "Tagged Results and Contents that contain images.");
|
||||
htmlModule.startDataType("Thumbnails", "Contains thumbnails of images that are associated with tagged files and results.");
|
||||
List<String> emptyHeaders = new ArrayList<>();
|
||||
for (int i = 0; i < ReportHTML.THUMBNAIL_COLUMNS; i++) {
|
||||
emptyHeaders.add("");
|
||||
}
|
||||
htmlModule.startTable(emptyHeaders);
|
||||
|
||||
htmlModule.addThumbnailRows(images);
|
||||
|
||||
htmlModule.endTable();
|
||||
htmlModule.endDataType();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Analyze artifact associated with tag and add to internal list if it is associated
|
||||
* with an image.
|
||||
* @param artifactTag
|
||||
*/
|
||||
private void checkIfTagHasImage(BlackboardArtifactTag artifactTag) {
|
||||
AbstractFile file;
|
||||
try {
|
||||
@ -638,34 +679,37 @@ public class ReportGenerator {
|
||||
logger.log(Level.WARNING, "Error while getting content from a blackboard artifact to report on.", ex);
|
||||
return;
|
||||
}
|
||||
|
||||
if (file.isDir() ||
|
||||
file.getType() == TskData.TSK_DB_FILES_TYPE_ENUM.UNALLOC_BLOCKS ||
|
||||
file.getType() == TskData.TSK_DB_FILES_TYPE_ENUM.UNUSED_BLOCKS) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Only include content for images
|
||||
if (ImageUtils.thumbnailSupported(file)) {
|
||||
images.add(file);
|
||||
}
|
||||
checkIfFileIsImage(file);
|
||||
}
|
||||
|
||||
/**
|
||||
* Analyze file that tag is associated with and determine if
|
||||
* it is an image and should have a thumbnail reported for it.
|
||||
* Images are added to internal list.
|
||||
* @param contentTag
|
||||
*/
|
||||
private void checkIfTagHasImage(ContentTag contentTag) {
|
||||
Content c = contentTag.getContent();
|
||||
if (c instanceof AbstractFile == false) {
|
||||
return;
|
||||
}
|
||||
AbstractFile file = (AbstractFile) c;
|
||||
checkIfFileIsImage((AbstractFile) c);
|
||||
}
|
||||
|
||||
/**
|
||||
* If file is an image file, add it to the internal 'images' list.
|
||||
* @param file
|
||||
*/
|
||||
private void checkIfFileIsImage(AbstractFile file) {
|
||||
|
||||
if (file.isDir() ||
|
||||
file.getType() == TskData.TSK_DB_FILES_TYPE_ENUM.UNALLOC_BLOCKS ||
|
||||
file.getType() == TskData.TSK_DB_FILES_TYPE_ENUM.UNUSED_BLOCKS) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (ImageUtils.thumbnailSupported(c)) {
|
||||
images.add(c);
|
||||
if (ImageUtils.thumbnailSupported(file)) {
|
||||
images.add(file);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -533,42 +533,13 @@ public class ReportHTML implements TableReportModule {
|
||||
return;
|
||||
}
|
||||
|
||||
// Make a folder for the local file with the same tagName as the tag.
|
||||
StringBuilder localFilePath = new StringBuilder();
|
||||
localFilePath.append(path);
|
||||
localFilePath.append(contentTag.getName().getDisplayName());
|
||||
File localFileFolder = new File(localFilePath.toString());
|
||||
if (!localFileFolder.exists()) {
|
||||
localFileFolder.mkdirs();
|
||||
}
|
||||
|
||||
// Construct a file tagName for the local file that incorporates the file id to ensure uniqueness.
|
||||
String fileName = file.getName();
|
||||
String objectIdSuffix = "_" + file.getId();
|
||||
int lastDotIndex = fileName.lastIndexOf(".");
|
||||
if (lastDotIndex != -1 && lastDotIndex != 0) {
|
||||
// The file tagName has a conventional extension. Insert the object id before the '.' of the extension.
|
||||
fileName = fileName.substring(0, lastDotIndex) + objectIdSuffix + fileName.substring(lastDotIndex, fileName.length());
|
||||
}
|
||||
else {
|
||||
// The file has no extension or the only '.' in the file is an initial '.', as in a hidden file.
|
||||
// Add the object id to the end of the file tagName.
|
||||
fileName += objectIdSuffix;
|
||||
}
|
||||
localFilePath.append(File.separator);
|
||||
localFilePath.append(fileName);
|
||||
|
||||
// If the local file doesn't already exist, create it now.
|
||||
// The existence check is necessary because it is possible to apply multiple tags with the same tagName to a file.
|
||||
File localFile = new File(localFilePath.toString());
|
||||
if (!localFile.exists()) {
|
||||
ExtractFscContentVisitor.extract(file, localFile, null, null);
|
||||
}
|
||||
// save it in a folder based on the tag name
|
||||
String localFilePath = saveContent(file, contentTag.getName().getDisplayName());
|
||||
|
||||
// Add the hyperlink to the row. A column header for it was created in startTable().
|
||||
StringBuilder localFileLink = new StringBuilder();
|
||||
localFileLink.append("<a href=\"file:///");
|
||||
localFileLink.append(localFilePath.toString());
|
||||
localFileLink.append(localFilePath);
|
||||
localFileLink.append("\">View File</a>");
|
||||
row.add(localFileLink.toString());
|
||||
|
||||
@ -628,17 +599,21 @@ public class ReportHTML implements TableReportModule {
|
||||
|
||||
AbstractFile file = (AbstractFile) content;
|
||||
|
||||
String contentPath = saveContent(file);
|
||||
// save copies of the orginal image and thumbnail image
|
||||
String thumbnailPath = prepareThumbnail(file);
|
||||
if (thumbnailPath == null) {
|
||||
continue;
|
||||
}
|
||||
String contentPath = saveContent(file, "thumbs_fullsize");
|
||||
|
||||
StringBuilder linkToThumbnail = new StringBuilder();
|
||||
linkToThumbnail.append("<a href=\"file:///");
|
||||
linkToThumbnail.append(contentPath);
|
||||
linkToThumbnail.append("\">");
|
||||
linkToThumbnail.append("<img src=\"").append(thumbnailPath).append("\" />");
|
||||
linkToThumbnail.append("</a>");
|
||||
linkToThumbnail.append("</a><br>");
|
||||
linkToThumbnail.append(file.getName()).append("<br>");
|
||||
// @@@ Add tags here
|
||||
currentRow.add(linkToThumbnail.toString());
|
||||
|
||||
totalCount++;
|
||||
@ -670,11 +645,21 @@ public class ReportHTML implements TableReportModule {
|
||||
return false;
|
||||
}
|
||||
|
||||
public String saveContent(AbstractFile file) {
|
||||
/**
|
||||
* Save a local copy of the given file in the reports folder.
|
||||
* @param file File to save
|
||||
* @param dirName Custom top-level folder to use to store the files in (tag name, etc.)
|
||||
* @return Path to where file was stored
|
||||
*/
|
||||
public String saveContent(AbstractFile file, String dirName) {
|
||||
// clean up the dir name passed in
|
||||
String dirName2 = dirName.replace("/", "_");
|
||||
dirName2 = dirName2.replace("\\", "_");
|
||||
|
||||
// Make a folder for the local file with the same tagName as the tag.
|
||||
StringBuilder localFilePath = new StringBuilder();
|
||||
localFilePath.append(path);
|
||||
localFilePath.append("tagged_images");
|
||||
localFilePath.append(dirName2);
|
||||
File localFileFolder = new File(localFilePath.toString());
|
||||
if (!localFileFolder.exists()) {
|
||||
localFileFolder.mkdirs();
|
||||
|
Loading…
x
Reference in New Issue
Block a user