mirror of
https://github.com/overcuriousity/autopsy-flatpak.git
synced 2025-07-14 17:06:16 +00:00
Merge pull request #398 from jawallace/thumbnail_reporting
Thumbnail reporting
This commit is contained in:
commit
cc1a7f7f47
@ -41,6 +41,7 @@ import org.openide.nodes.NodeListener;
|
|||||||
import org.openide.nodes.NodeMemberEvent;
|
import org.openide.nodes.NodeMemberEvent;
|
||||||
import org.openide.nodes.NodeReorderEvent;
|
import org.openide.nodes.NodeReorderEvent;
|
||||||
import org.sleuthkit.autopsy.corecomponentinterfaces.DataResultViewer;
|
import org.sleuthkit.autopsy.corecomponentinterfaces.DataResultViewer;
|
||||||
|
import org.sleuthkit.autopsy.coreutils.ImageUtils;
|
||||||
import org.sleuthkit.datamodel.AbstractFile;
|
import org.sleuthkit.datamodel.AbstractFile;
|
||||||
import org.sleuthkit.datamodel.TskCoreException;
|
import org.sleuthkit.datamodel.TskCoreException;
|
||||||
|
|
||||||
@ -63,7 +64,7 @@ public final class DataResultViewerThumbnail extends AbstractDataResultViewer {
|
|||||||
private int curPage;
|
private int curPage;
|
||||||
private int totalPages;
|
private int totalPages;
|
||||||
private int curPageImages;
|
private int curPageImages;
|
||||||
private int iconSize = ThumbnailViewNode.ICON_SIZE_MEDIUM;
|
private int iconSize = ImageUtils.ICON_SIZE_MEDIUM;
|
||||||
private final PageUpdater pageUpdater = new PageUpdater();
|
private final PageUpdater pageUpdater = new PageUpdater();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -240,13 +241,13 @@ public final class DataResultViewerThumbnail extends AbstractDataResultViewer {
|
|||||||
|
|
||||||
private void thumbnailSizeComboBoxActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_thumbnailSizeComboBoxActionPerformed
|
private void thumbnailSizeComboBoxActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_thumbnailSizeComboBoxActionPerformed
|
||||||
|
|
||||||
iconSize = ThumbnailViewNode.ICON_SIZE_MEDIUM; //default size
|
iconSize = ImageUtils.ICON_SIZE_MEDIUM; //default size
|
||||||
switch(thumbnailSizeComboBox.getSelectedIndex()) {
|
switch(thumbnailSizeComboBox.getSelectedIndex()) {
|
||||||
case 0:
|
case 0:
|
||||||
iconSize = ThumbnailViewNode.ICON_SIZE_SMALL;
|
iconSize = ImageUtils.ICON_SIZE_SMALL;
|
||||||
break;
|
break;
|
||||||
case 2:
|
case 2:
|
||||||
iconSize = ThumbnailViewNode.ICON_SIZE_LARGE;
|
iconSize = ImageUtils.ICON_SIZE_LARGE;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -21,21 +21,13 @@ package org.sleuthkit.autopsy.corecomponents;
|
|||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import javax.imageio.ImageIO;
|
|
||||||
import org.openide.nodes.AbstractNode;
|
import org.openide.nodes.AbstractNode;
|
||||||
import org.openide.nodes.Children;
|
import org.openide.nodes.Children;
|
||||||
import org.openide.nodes.Node;
|
import org.openide.nodes.Node;
|
||||||
import org.openide.util.lookup.Lookups;
|
import org.openide.util.lookup.Lookups;
|
||||||
import org.sleuthkit.autopsy.contentviewers.Utilities;
|
import org.sleuthkit.autopsy.coreutils.ImageUtils;
|
||||||
import org.sleuthkit.autopsy.coreutils.Logger;
|
import org.sleuthkit.autopsy.coreutils.Logger;
|
||||||
import org.sleuthkit.datamodel.AbstractFile;
|
|
||||||
import org.sleuthkit.datamodel.Content;
|
import org.sleuthkit.datamodel.Content;
|
||||||
import org.sleuthkit.datamodel.ContentVisitor;
|
|
||||||
import org.sleuthkit.datamodel.DerivedFile;
|
|
||||||
import org.sleuthkit.datamodel.File;
|
|
||||||
import org.sleuthkit.datamodel.LocalFile;
|
|
||||||
import org.sleuthkit.datamodel.LayoutFile;
|
|
||||||
import org.sleuthkit.datamodel.TskCoreException;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Complementary class to ThumbnailViewNode. Children node factory. Wraps around
|
* Complementary class to ThumbnailViewNode. Children node factory. Wraps around
|
||||||
@ -49,13 +41,12 @@ import org.sleuthkit.datamodel.TskCoreException;
|
|||||||
*/
|
*/
|
||||||
class ThumbnailViewChildren extends Children.Keys<Integer> {
|
class ThumbnailViewChildren extends Children.Keys<Integer> {
|
||||||
|
|
||||||
private static final IsSupportedContentVisitor isSupportedVisitor = new IsSupportedContentVisitor();
|
|
||||||
static final int IMAGES_PER_PAGE = 200;
|
static final int IMAGES_PER_PAGE = 200;
|
||||||
private Node parent;
|
private Node parent;
|
||||||
private final HashMap<Integer, List<Node>> pages = new HashMap<Integer, List<Node>>();
|
private final HashMap<Integer, List<Node>> pages = new HashMap<Integer, List<Node>>();
|
||||||
private int totalImages = 0;
|
private int totalImages = 0;
|
||||||
private int totalPages = 0;
|
private int totalPages = 0;
|
||||||
private int iconSize = ThumbnailViewNode.ICON_SIZE_MEDIUM;
|
private int iconSize = ImageUtils.ICON_SIZE_MEDIUM;
|
||||||
private static final Logger logger = Logger.getLogger(ThumbnailViewChildren.class.getName());
|
private static final Logger logger = Logger.getLogger(ThumbnailViewChildren.class.getName());
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -152,7 +143,7 @@ class ThumbnailViewChildren extends Children.Keys<Integer> {
|
|||||||
if (node != null) {
|
if (node != null) {
|
||||||
Content content = node.getLookup().lookup(Content.class);
|
Content content = node.getLookup().lookup(Content.class);
|
||||||
if (content != null) {
|
if (content != null) {
|
||||||
return content.accept(isSupportedVisitor);
|
return ImageUtils.thumbnailSupported(content);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
@ -162,59 +153,6 @@ class ThumbnailViewChildren extends Children.Keys<Integer> {
|
|||||||
this.iconSize = iconSize;
|
this.iconSize = iconSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static class IsSupportedContentVisitor extends ContentVisitor.Default<Boolean> {
|
|
||||||
|
|
||||||
private final List<String> SUPP_EXTENSIONS;
|
|
||||||
|
|
||||||
IsSupportedContentVisitor() {
|
|
||||||
String[] supportedImagesSuffixes = ImageIO.getReaderFileSuffixes();
|
|
||||||
|
|
||||||
SUPP_EXTENSIONS = new ArrayList<String>(supportedImagesSuffixes.length);
|
|
||||||
for (int i = 0; i < supportedImagesSuffixes.length; ++i) {
|
|
||||||
String suffix = supportedImagesSuffixes[i];
|
|
||||||
SUPP_EXTENSIONS.add("." + suffix);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Boolean visit(DerivedFile f) {
|
|
||||||
return isSupported(f);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Boolean visit(LocalFile f) {
|
|
||||||
return isSupported(f);
|
|
||||||
}
|
|
||||||
|
|
||||||
public Boolean visit(LayoutFile f) {
|
|
||||||
return isSupported(f);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Boolean visit(File f) {
|
|
||||||
return isSupported(f);
|
|
||||||
}
|
|
||||||
|
|
||||||
public Boolean isSupported(AbstractFile f) {
|
|
||||||
final String fName = f.getName();
|
|
||||||
final int dotIdx = fName.lastIndexOf('.');
|
|
||||||
if (dotIdx == -1) {
|
|
||||||
return Utilities.isJpegFileHeader(f);
|
|
||||||
}
|
|
||||||
|
|
||||||
final String ext = fName.substring(dotIdx).toLowerCase();
|
|
||||||
|
|
||||||
// Note: thumbnail generator only supports JPG, GIF, and PNG for now
|
|
||||||
return (f.getSize() > 0
|
|
||||||
&& SUPP_EXTENSIONS.contains(ext));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected Boolean defaultVisit(Content cntnt) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Node representing page node, a parent of image nodes, with a name showing
|
* Node representing page node, a parent of image nodes, with a name showing
|
||||||
* children range
|
* children range
|
||||||
|
@ -18,30 +18,12 @@
|
|||||||
*/
|
*/
|
||||||
package org.sleuthkit.autopsy.corecomponents;
|
package org.sleuthkit.autopsy.corecomponents;
|
||||||
|
|
||||||
import java.awt.Color;
|
|
||||||
import java.awt.Graphics2D;
|
|
||||||
import java.awt.Image;
|
import java.awt.Image;
|
||||||
import java.awt.MediaTracker;
|
|
||||||
import java.awt.Toolkit;
|
|
||||||
import java.awt.image.BufferedImage;
|
|
||||||
import java.io.File;
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.io.InputStream;
|
|
||||||
import java.lang.ref.SoftReference;
|
import java.lang.ref.SoftReference;
|
||||||
import java.util.logging.Level;
|
|
||||||
import javax.imageio.ImageIO;
|
|
||||||
import javax.swing.ImageIcon;
|
|
||||||
import javax.swing.JFrame;
|
|
||||||
import org.openide.nodes.Children;
|
|
||||||
import org.openide.nodes.FilterNode;
|
import org.openide.nodes.FilterNode;
|
||||||
import org.openide.nodes.Node;
|
import org.openide.nodes.Node;
|
||||||
import org.openide.util.Exceptions;
|
import org.sleuthkit.autopsy.coreutils.ImageUtils;
|
||||||
import org.sleuthkit.autopsy.casemodule.Case;
|
|
||||||
import org.sleuthkit.autopsy.corelibs.ScalrWrapper;
|
|
||||||
import org.sleuthkit.autopsy.coreutils.Logger;
|
|
||||||
import org.sleuthkit.datamodel.Content;
|
import org.sleuthkit.datamodel.Content;
|
||||||
import org.sleuthkit.datamodel.ReadContentInputStream;
|
|
||||||
import org.sleuthkit.datamodel.TskException;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Node that wraps around original node and adds the bitmap icon representing
|
* Node that wraps around original node and adds the bitmap icon representing
|
||||||
@ -50,12 +32,7 @@ import org.sleuthkit.datamodel.TskException;
|
|||||||
class ThumbnailViewNode extends FilterNode {
|
class ThumbnailViewNode extends FilterNode {
|
||||||
|
|
||||||
private SoftReference<Image> iconCache = null;
|
private SoftReference<Image> iconCache = null;
|
||||||
private static final Image defaultIcon = new ImageIcon("/org/sleuthkit/autopsy/images/file-icon.png").getImage();
|
private int iconSize = ImageUtils.ICON_SIZE_MEDIUM;
|
||||||
private static final Logger logger = Logger.getLogger(ThumbnailViewNode.class.getName());
|
|
||||||
static final int ICON_SIZE_SMALL = 50;
|
|
||||||
static final int ICON_SIZE_MEDIUM = 100;
|
|
||||||
static final int ICON_SIZE_LARGE = 200;
|
|
||||||
private int iconSize = ICON_SIZE_MEDIUM;
|
|
||||||
//private final BufferedImage defaultIconBI;
|
//private final BufferedImage defaultIconBI;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -87,90 +64,16 @@ class ThumbnailViewNode extends FilterNode {
|
|||||||
Content content = this.getLookup().lookup(Content.class);
|
Content content = this.getLookup().lookup(Content.class);
|
||||||
|
|
||||||
if (content != null) {
|
if (content != null) {
|
||||||
// If a thumbnail file is already saved locally
|
icon = ImageUtils.getIcon(content, iconSize);
|
||||||
if (getFile(content.getId()).exists()) {
|
|
||||||
try {
|
|
||||||
BufferedImage bicon = ImageIO.read(getFile(content.getId()));
|
|
||||||
if (bicon == null) {
|
|
||||||
icon = ThumbnailViewNode.defaultIcon;
|
|
||||||
} else if (bicon.getWidth() != iconSize) {
|
|
||||||
icon = generateAndSaveIcon(content);
|
|
||||||
} else {
|
|
||||||
icon = bicon;
|
|
||||||
}
|
|
||||||
} catch (IOException ex) {
|
|
||||||
icon = ThumbnailViewNode.defaultIcon;
|
|
||||||
}
|
|
||||||
} else { // Make a new icon
|
|
||||||
icon = generateAndSaveIcon(content);
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
icon = ThumbnailViewNode.defaultIcon;
|
icon = ImageUtils.getDefaultIcon();
|
||||||
}
|
}
|
||||||
|
|
||||||
iconCache = new SoftReference<Image>(icon);
|
iconCache = new SoftReference<>(icon);
|
||||||
}
|
}
|
||||||
|
|
||||||
return icon;
|
return icon;
|
||||||
}
|
}
|
||||||
|
|
||||||
private Image generateAndSaveIcon(Content content) {
|
|
||||||
Image icon = null;
|
|
||||||
try {
|
|
||||||
icon = generateIcon(content);
|
|
||||||
if (icon == null) {
|
|
||||||
icon = ThumbnailViewNode.defaultIcon;
|
|
||||||
} else {
|
|
||||||
File f = getFile(content.getId());
|
|
||||||
if (f.exists()) {
|
|
||||||
f.delete();
|
|
||||||
}
|
|
||||||
ImageIO.write((BufferedImage) icon, "jpg", getFile(content.getId()));
|
|
||||||
}
|
|
||||||
} catch (IOException ex) {
|
|
||||||
logger.log(Level.WARNING, "Could not write cache thumbnail: " + content, ex);
|
|
||||||
}
|
|
||||||
return icon;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Generate a scaled image
|
|
||||||
*/
|
|
||||||
private BufferedImage generateIcon(Content content) {
|
|
||||||
|
|
||||||
InputStream inputStream = null;
|
|
||||||
try {
|
|
||||||
inputStream = new ReadContentInputStream(content);
|
|
||||||
BufferedImage bi = ImageIO.read(inputStream);
|
|
||||||
if (bi == null) {
|
|
||||||
logger.log(Level.WARNING, "No image reader for file: " + content.getName());
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
BufferedImage biScaled = ScalrWrapper.resizeFast(bi, iconSize);
|
|
||||||
|
|
||||||
return biScaled;
|
|
||||||
}catch (OutOfMemoryError e) {
|
|
||||||
logger.log(Level.WARNING, "Could not scale image (too large): " + content.getName(), e);
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
catch (Exception e) {
|
|
||||||
logger.log(Level.WARNING, "Could not scale image: " + content.getName(), e);
|
|
||||||
return null;
|
|
||||||
} finally {
|
|
||||||
if (inputStream != null) {
|
|
||||||
try {
|
|
||||||
inputStream.close();
|
|
||||||
} catch (IOException ex) {
|
|
||||||
logger.log(Level.WARNING, "Could not close input stream after resizing thumbnail: " + content.getName(), ex);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static File getFile(long id) {
|
|
||||||
return new File(Case.getCurrentCase().getCacheDirectory() + File.separator + id + ".jpg");
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setIconSize(int iconSize) {
|
public void setIconSize(int iconSize) {
|
||||||
this.iconSize = iconSize;
|
this.iconSize = iconSize;
|
||||||
|
196
Core/src/org/sleuthkit/autopsy/coreutils/ImageUtils.java
Executable file
196
Core/src/org/sleuthkit/autopsy/coreutils/ImageUtils.java
Executable file
@ -0,0 +1,196 @@
|
|||||||
|
/*
|
||||||
|
*
|
||||||
|
* Autopsy Forensic Browser
|
||||||
|
*
|
||||||
|
* Copyright 2012 Basis Technology Corp.
|
||||||
|
*
|
||||||
|
* Copyright 2012 42six Solutions.
|
||||||
|
* Contact: aebadirad <at> 42six <dot> com
|
||||||
|
* Project Contact/Architect: 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.coreutils;
|
||||||
|
|
||||||
|
import java.awt.Image;
|
||||||
|
import java.awt.image.BufferedImage;
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.logging.Level;
|
||||||
|
import javax.imageio.ImageIO;
|
||||||
|
import javax.swing.ImageIcon;
|
||||||
|
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.Content;
|
||||||
|
import org.sleuthkit.datamodel.ReadContentInputStream;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Utilities for creating and manipulating thumbnail and icon images.
|
||||||
|
* @author jwallace
|
||||||
|
*/
|
||||||
|
public class ImageUtils {
|
||||||
|
public static final int ICON_SIZE_SMALL = 50;
|
||||||
|
public static final int ICON_SIZE_MEDIUM = 100;
|
||||||
|
public static final int ICON_SIZE_LARGE = 200;
|
||||||
|
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());
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the default Icon, which is the icon for a file.
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public static Image getDefaultIcon() {
|
||||||
|
return DEFAULT_ICON;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Can a thumbnail be generated for the content?
|
||||||
|
*
|
||||||
|
* @param content
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public static boolean thumbnailSupported(Content content) {
|
||||||
|
if (content instanceof AbstractFile == false) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
AbstractFile f = (AbstractFile) content;
|
||||||
|
final String fName = f.getName();
|
||||||
|
final int dotIdx = fName.lastIndexOf('.');
|
||||||
|
if (dotIdx == -1 || dotIdx == (fName.length() - 1)) {
|
||||||
|
return Utilities.isJpegFileHeader(f);
|
||||||
|
}
|
||||||
|
|
||||||
|
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));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get an icon of a specified size.
|
||||||
|
*
|
||||||
|
* @param content
|
||||||
|
* @param iconSize
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public static Image getIcon(Content content, int iconSize) {
|
||||||
|
Image icon;
|
||||||
|
// If a thumbnail file is already saved locally
|
||||||
|
File file = getFile(content.getId());
|
||||||
|
if (file.exists()) {
|
||||||
|
try {
|
||||||
|
BufferedImage bicon = ImageIO.read(file);
|
||||||
|
if (bicon == null) {
|
||||||
|
icon = DEFAULT_ICON;
|
||||||
|
} else if (bicon.getWidth() != iconSize) {
|
||||||
|
icon = generateAndSaveIcon(content, iconSize);
|
||||||
|
} else {
|
||||||
|
icon = bicon;
|
||||||
|
}
|
||||||
|
} catch (IOException ex) {
|
||||||
|
logger.log(Level.WARNING, "Error while reading image.", ex);
|
||||||
|
icon = DEFAULT_ICON;
|
||||||
|
}
|
||||||
|
} else { // Make a new icon
|
||||||
|
icon = generateAndSaveIcon(content, iconSize);
|
||||||
|
}
|
||||||
|
return icon;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the cached file of the icon. Generates the icon and its file if it
|
||||||
|
* doesn't already exist, so this method guarantees to return a file that
|
||||||
|
* exists.
|
||||||
|
* @param content
|
||||||
|
* @param iconSize
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public static File getIconFile(Content content, int iconSize) {
|
||||||
|
getIcon(content, iconSize);
|
||||||
|
return getFile(content.getId());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the cached file of the content object with the given id.
|
||||||
|
*
|
||||||
|
* The returned file may not exist.
|
||||||
|
*
|
||||||
|
* @param id
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public static File getFile(long id) {
|
||||||
|
return new File(Case.getCurrentCase().getCacheDirectory() + File.separator + id + ".jpg");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private static Image generateAndSaveIcon(Content content, int iconSize) {
|
||||||
|
Image icon = null;
|
||||||
|
try {
|
||||||
|
icon = generateIcon(content, iconSize);
|
||||||
|
if (icon == null) {
|
||||||
|
return DEFAULT_ICON;
|
||||||
|
} else {
|
||||||
|
File f = getFile(content.getId());
|
||||||
|
if (f.exists()) {
|
||||||
|
f.delete();
|
||||||
|
}
|
||||||
|
ImageIO.write((BufferedImage) icon, "jpg", getFile(content.getId()));
|
||||||
|
}
|
||||||
|
} catch (IOException ex) {
|
||||||
|
logger.log(Level.WARNING, "Could not write cache thumbnail: " + content, ex);
|
||||||
|
}
|
||||||
|
return icon;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Generate a scaled image
|
||||||
|
*/
|
||||||
|
private static BufferedImage generateIcon(Content content, int iconSize) {
|
||||||
|
|
||||||
|
InputStream inputStream = null;
|
||||||
|
try {
|
||||||
|
inputStream = new ReadContentInputStream(content);
|
||||||
|
BufferedImage bi = ImageIO.read(inputStream);
|
||||||
|
if (bi == null) {
|
||||||
|
logger.log(Level.WARNING, "No image reader for file: " + content.getName());
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
BufferedImage biScaled = ScalrWrapper.resizeFast(bi, iconSize);
|
||||||
|
|
||||||
|
return biScaled;
|
||||||
|
} catch (OutOfMemoryError e) {
|
||||||
|
logger.log(Level.WARNING, "Could not scale image (too large): " + content.getName(), e);
|
||||||
|
return null;
|
||||||
|
} catch (Exception e) {
|
||||||
|
logger.log(Level.WARNING, "Could not scale image: " + content.getName(), e);
|
||||||
|
return null;
|
||||||
|
} finally {
|
||||||
|
if (inputStream != null) {
|
||||||
|
try {
|
||||||
|
inputStream.close();
|
||||||
|
} catch (IOException ex) {
|
||||||
|
logger.log(Level.WARNING, "Could not close input stream after resizing thumbnail: " + content.getName(), ex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -48,6 +48,7 @@ import javax.swing.SwingWorker;
|
|||||||
import org.openide.filesystems.FileUtil;
|
import org.openide.filesystems.FileUtil;
|
||||||
import org.sleuthkit.autopsy.casemodule.Case;
|
import org.sleuthkit.autopsy.casemodule.Case;
|
||||||
import org.sleuthkit.autopsy.coreutils.EscapeUtil;
|
import org.sleuthkit.autopsy.coreutils.EscapeUtil;
|
||||||
|
import org.sleuthkit.autopsy.coreutils.ImageUtils;
|
||||||
import org.sleuthkit.autopsy.coreutils.Logger;
|
import org.sleuthkit.autopsy.coreutils.Logger;
|
||||||
import org.sleuthkit.autopsy.coreutils.MessageNotifyUtil;
|
import org.sleuthkit.autopsy.coreutils.MessageNotifyUtil;
|
||||||
import org.sleuthkit.autopsy.report.ReportProgressPanel.ReportStatus;
|
import org.sleuthkit.autopsy.report.ReportProgressPanel.ReportStatus;
|
||||||
@ -57,9 +58,11 @@ import org.sleuthkit.datamodel.BlackboardArtifact.ARTIFACT_TYPE;
|
|||||||
import org.sleuthkit.datamodel.BlackboardArtifactTag;
|
import org.sleuthkit.datamodel.BlackboardArtifactTag;
|
||||||
import org.sleuthkit.datamodel.BlackboardAttribute;
|
import org.sleuthkit.datamodel.BlackboardAttribute;
|
||||||
import org.sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE;
|
import org.sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE;
|
||||||
|
import org.sleuthkit.datamodel.Content;
|
||||||
import org.sleuthkit.datamodel.ContentTag;
|
import org.sleuthkit.datamodel.ContentTag;
|
||||||
import org.sleuthkit.datamodel.SleuthkitCase;
|
import org.sleuthkit.datamodel.SleuthkitCase;
|
||||||
import org.sleuthkit.datamodel.TskCoreException;
|
import org.sleuthkit.datamodel.TskCoreException;
|
||||||
|
import org.sleuthkit.datamodel.TskException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Instances of this class use GeneralReportModules, TableReportModules and
|
* Instances of this class use GeneralReportModules, TableReportModules and
|
||||||
@ -462,7 +465,7 @@ public class ReportGenerator {
|
|||||||
}
|
}
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
module.addRow(rowData);
|
module.addRow(rowData);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -565,15 +568,31 @@ public class ReportGenerator {
|
|||||||
comment.append("This report only includes results tagged with: ");
|
comment.append("This report only includes results tagged with: ");
|
||||||
comment.append(makeCommaSeparatedList(tagNamesFilter));
|
comment.append(makeCommaSeparatedList(tagNamesFilter));
|
||||||
}
|
}
|
||||||
module.startDataType(ARTIFACT_TYPE.TSK_TAG_ARTIFACT.getDisplayName(), comment.toString());
|
module.startDataType(ARTIFACT_TYPE.TSK_TAG_ARTIFACT.getDisplayName(), comment.toString());
|
||||||
module.startTable(new ArrayList<>(Arrays.asList("Result Type", "Tag", "Comment", "Source File")));
|
String[] tableHeaders;
|
||||||
|
if (module instanceof ReportHTML) {
|
||||||
|
tableHeaders = new String[] {"Result Type", "Tag", "Comment", "Source File", "Thumbnail"};
|
||||||
|
} else {
|
||||||
|
tableHeaders = new String[] {"Result Type", "Tag", "Comment", "Source File"};
|
||||||
|
}
|
||||||
|
module.startTable(new ArrayList<>(Arrays.asList(tableHeaders)));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Give the modules the rows for the content tags.
|
// Give the modules the rows for the content tags.
|
||||||
for (BlackboardArtifactTag tag : tags) {
|
for (BlackboardArtifactTag tag : tags) {
|
||||||
if (passesTagNamesFilter(tag.getName().getDisplayName())) {
|
if (passesTagNamesFilter(tag.getName().getDisplayName())) {
|
||||||
|
List<String> row;
|
||||||
|
File thumbFile;
|
||||||
for (TableReportModule module : tableModules) {
|
for (TableReportModule module : tableModules) {
|
||||||
module.addRow(new ArrayList<>(Arrays.asList(tag.getArtifact().getArtifactTypeName(), tag.getName().getDisplayName(), tag.getComment(), tag.getContent().getName())));
|
// We have specific behavior if the module is a ReportHTML.
|
||||||
|
// We add a thumbnail if the artifact is associated with an
|
||||||
|
// image file.
|
||||||
|
row = new ArrayList<>(Arrays.asList(tag.getArtifact().getArtifactTypeName(), tag.getName().getDisplayName(), tag.getComment(), tag.getContent().getName()));
|
||||||
|
if (module instanceof ReportHTML) {
|
||||||
|
((ReportHTML) module).addRowWithTaggedContentHyperlink(row, tag);
|
||||||
|
} else {
|
||||||
|
module.addRow(row);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -598,7 +617,7 @@ public class ReportGenerator {
|
|||||||
iter.remove();
|
iter.remove();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// @@@ Should move the methods specific to TableReportsWorker into that scope.
|
/// @@@ Should move the methods specific to TableReportsWorker into that scope.
|
||||||
@ -1334,21 +1353,6 @@ public class ReportGenerator {
|
|||||||
private Map<Integer,String> getMappedAttributes() {
|
private Map<Integer,String> getMappedAttributes() {
|
||||||
return ReportGenerator.this.getMappedAttributes(attributes);
|
return ReportGenerator.this.getMappedAttributes(attributes);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Get a BlackboardArtifact.
|
|
||||||
*
|
|
||||||
* @param long artifactId An artifact id
|
|
||||||
* @return The BlackboardArtifact associated with the artifact id
|
|
||||||
*/
|
|
||||||
private BlackboardArtifact getArtifactByID(long artifactId) {
|
|
||||||
try {
|
|
||||||
return skCase.getBlackboardArtifact(artifactId);
|
|
||||||
} catch (TskCoreException ex) {
|
|
||||||
logger.log(Level.WARNING, "Failed to get blackboard artifact by ID.", ex);
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -39,9 +39,10 @@ import java.util.List;
|
|||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.TreeMap;
|
import java.util.TreeMap;
|
||||||
import java.util.logging.Level;
|
import java.util.logging.Level;
|
||||||
import org.openide.filesystems.FileUtil;
|
|
||||||
import org.openide.util.Exceptions;
|
import org.openide.util.Exceptions;
|
||||||
import org.sleuthkit.autopsy.casemodule.Case;
|
import org.sleuthkit.autopsy.casemodule.Case;
|
||||||
|
import org.openide.filesystems.FileUtil;
|
||||||
|
import org.sleuthkit.autopsy.coreutils.ImageUtils;
|
||||||
import org.sleuthkit.autopsy.coreutils.Logger;
|
import org.sleuthkit.autopsy.coreutils.Logger;
|
||||||
import org.sleuthkit.autopsy.datamodel.ContentUtils.ExtractFscContentVisitor;
|
import org.sleuthkit.autopsy.datamodel.ContentUtils.ExtractFscContentVisitor;
|
||||||
import org.sleuthkit.autopsy.ingest.IngestManager;
|
import org.sleuthkit.autopsy.ingest.IngestManager;
|
||||||
@ -51,17 +52,20 @@ import org.sleuthkit.datamodel.SleuthkitCase;
|
|||||||
import org.sleuthkit.datamodel.TskCoreException;
|
import org.sleuthkit.datamodel.TskCoreException;
|
||||||
import org.sleuthkit.datamodel.BlackboardArtifact;
|
import org.sleuthkit.datamodel.BlackboardArtifact;
|
||||||
import org.sleuthkit.datamodel.BlackboardArtifact.ARTIFACT_TYPE;
|
import org.sleuthkit.datamodel.BlackboardArtifact.ARTIFACT_TYPE;
|
||||||
|
import org.sleuthkit.datamodel.BlackboardArtifactTag;
|
||||||
import org.sleuthkit.datamodel.ContentTag;
|
import org.sleuthkit.datamodel.ContentTag;
|
||||||
import org.sleuthkit.datamodel.TskData.TSK_DB_FILES_TYPE_ENUM;
|
import org.sleuthkit.datamodel.TskData.TSK_DB_FILES_TYPE_ENUM;
|
||||||
|
|
||||||
public class ReportHTML implements TableReportModule {
|
public class ReportHTML implements TableReportModule {
|
||||||
private static final Logger logger = Logger.getLogger(ReportHTML.class.getName());
|
private static final Logger logger = Logger.getLogger(ReportHTML.class.getName());
|
||||||
|
private static final String THUMBS_REL_PATH = "thumbs" + File.separator;
|
||||||
private static ReportHTML instance;
|
private static ReportHTML instance;
|
||||||
private Case currentCase;
|
private Case currentCase;
|
||||||
private SleuthkitCase skCase;
|
private SleuthkitCase skCase;
|
||||||
|
|
||||||
private Map<String, Integer> dataTypes;
|
private Map<String, Integer> dataTypes;
|
||||||
private String path;
|
private String path;
|
||||||
|
private String thumbsPath;
|
||||||
private String currentDataType; // name of current data type
|
private String currentDataType; // name of current data type
|
||||||
private Integer rowCount; // number of rows (aka artifacts or tags) for the current data type
|
private Integer rowCount; // number of rows (aka artifacts or tags) for the current data type
|
||||||
private Writer out;
|
private Writer out;
|
||||||
@ -90,6 +94,7 @@ public class ReportHTML implements TableReportModule {
|
|||||||
dataTypes = new TreeMap<>();
|
dataTypes = new TreeMap<>();
|
||||||
|
|
||||||
path = "";
|
path = "";
|
||||||
|
thumbsPath = "";
|
||||||
currentDataType = "";
|
currentDataType = "";
|
||||||
rowCount = 0;
|
rowCount = 0;
|
||||||
|
|
||||||
@ -266,8 +271,10 @@ public class ReportHTML implements TableReportModule {
|
|||||||
refresh();
|
refresh();
|
||||||
// Setup the path for the HTML report
|
// Setup the path for the HTML report
|
||||||
this.path = path + "HTML Report" + File.separator;
|
this.path = path + "HTML Report" + File.separator;
|
||||||
|
this.thumbsPath = this.path + "thumbs" + File.separator;
|
||||||
try {
|
try {
|
||||||
FileUtil.createFolder(new File(this.path));
|
FileUtil.createFolder(new File(this.path));
|
||||||
|
FileUtil.createFolder(new File(this.thumbsPath));
|
||||||
} catch (IOException ex) {
|
} catch (IOException ex) {
|
||||||
logger.log(Level.SEVERE, "Unable to make HTML report folder.");
|
logger.log(Level.SEVERE, "Unable to make HTML report folder.");
|
||||||
}
|
}
|
||||||
@ -499,21 +506,67 @@ public class ReportHTML implements TableReportModule {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Saves a local copy of a tagged file and adds a row with a hyper link to
|
* Saves a local copy of a tagged file and adds a row with a hyper link to
|
||||||
* the file.
|
* the file. The hyper link will be a thumbnail if the Content associated
|
||||||
|
* with the given ContentTag is an image.
|
||||||
*
|
*
|
||||||
* @param row Values for each data cell in the row.
|
* @param row Values for each data cell in the row.
|
||||||
* @param contentTag A content tag to use to make the hyper link.
|
* @param contentTag A content tag to use to make the hyper link.
|
||||||
*/
|
*/
|
||||||
public void addRowWithTaggedContentHyperlink(List<String> row, ContentTag contentTag) {
|
public void addRowWithTaggedContentHyperlink(List<String> row, ContentTag contentTag) {
|
||||||
// Only handling AbstractFiles at present.
|
// Only handling AbstractFiles at present.
|
||||||
|
String tagName = contentTag.getName().getDisplayName();
|
||||||
AbstractFile file;
|
AbstractFile file;
|
||||||
if (contentTag.getContent() instanceof AbstractFile) {
|
if (contentTag.getContent() instanceof AbstractFile) {
|
||||||
file = (AbstractFile)contentTag.getContent();
|
file = (AbstractFile)contentTag.getContent();
|
||||||
|
StringBuilder linkContent = new StringBuilder();
|
||||||
|
if (ImageUtils.thumbnailSupported(file)) {
|
||||||
|
linkContent.append("<img src=\"").append(prepareThumbnail(file)).append("\" />");
|
||||||
|
} else {
|
||||||
|
linkContent.append("View File");
|
||||||
|
}
|
||||||
|
addRowWithTaggedContentHyperlink(row, file, tagName, linkContent.toString());
|
||||||
}
|
}
|
||||||
else {
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Saves a local copy of a tagged file and adds a row with a hyper link to
|
||||||
|
* the file. The hyper link will be a thumbnail if the Content associated
|
||||||
|
* with the given BlackboardArtifactTag is an image.
|
||||||
|
*
|
||||||
|
* @param row Values for each data cell in the row.
|
||||||
|
* @param artifactTag An artifact tag to use to make the hyper link.
|
||||||
|
*/
|
||||||
|
public void addRowWithTaggedContentHyperlink(List<String> row, BlackboardArtifactTag artifactTag) {
|
||||||
|
String tagName = artifactTag.getName().getDisplayName();
|
||||||
|
AbstractFile file;
|
||||||
|
try {
|
||||||
|
file = Case.getCurrentCase().getSleuthkitCase().getAbstractFileById(artifactTag.getArtifact().getObjectID());
|
||||||
|
} catch (TskCoreException ex) {
|
||||||
|
logger.log(Level.WARNING, "Error while getting content from a blackboard artifact to report on.", ex);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Only include content for images
|
||||||
|
if (ImageUtils.thumbnailSupported(file)) {
|
||||||
|
StringBuilder linkContent = new StringBuilder();
|
||||||
|
linkContent.append("<img src=\"").append(prepareThumbnail(file)).append("\" />");
|
||||||
|
addRowWithTaggedContentHyperlink(row, file, tagName, linkContent.toString());
|
||||||
|
} else {
|
||||||
|
row.add("");
|
||||||
|
this.addRow(row);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Saves a local copy of a tagged file and adds a row with a hyper link to
|
||||||
|
* the file. The content of the hyperlink is provided in linkHTMLContent.
|
||||||
|
*
|
||||||
|
* @param row Values for each data cell in the row
|
||||||
|
* @param file The file to link to in the report.
|
||||||
|
* @param tagName the name of the tag that the content was flagged by
|
||||||
|
* @param linkHTMLContent the html that will be the body of the link
|
||||||
|
*/
|
||||||
|
private void addRowWithTaggedContentHyperlink(List<String> row, AbstractFile file, String tagName, String linkHTMLContent) {
|
||||||
// Don't make a local copy of the file if it is a directory or unallocated space.
|
// Don't make a local copy of the file if it is a directory or unallocated space.
|
||||||
if (file.isDir() ||
|
if (file.isDir() ||
|
||||||
file.getType() == TSK_DB_FILES_TYPE_ENUM.UNALLOC_BLOCKS ||
|
file.getType() == TSK_DB_FILES_TYPE_ENUM.UNALLOC_BLOCKS ||
|
||||||
@ -522,43 +575,45 @@ public class ReportHTML implements TableReportModule {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Make a folder for the local file with the same name as the tag.
|
// Make a folder for the local file with the same tagName as the tag.
|
||||||
StringBuilder localFilePath = new StringBuilder();
|
StringBuilder localFilePath = new StringBuilder();
|
||||||
localFilePath.append(path);
|
localFilePath.append(path);
|
||||||
localFilePath.append(contentTag.getName().getDisplayName());
|
localFilePath.append(tagName);
|
||||||
File localFileFolder = new File(localFilePath.toString());
|
File localFileFolder = new File(localFilePath.toString());
|
||||||
if (!localFileFolder.exists()) {
|
if (!localFileFolder.exists()) {
|
||||||
localFileFolder.mkdirs();
|
localFileFolder.mkdirs();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Construct a file name for the local file that incorporates the file id to ensure uniqueness.
|
// Construct a file tagName for the local file that incorporates the file id to ensure uniqueness.
|
||||||
String fileName = file.getName();
|
String fileName = file.getName();
|
||||||
String objectIdSuffix = "_" + file.getId();
|
String objectIdSuffix = "_" + file.getId();
|
||||||
int lastDotIndex = fileName.lastIndexOf(".");
|
int lastDotIndex = fileName.lastIndexOf(".");
|
||||||
if (lastDotIndex != -1 && lastDotIndex != 0) {
|
if (lastDotIndex != -1 && lastDotIndex != 0) {
|
||||||
// The file name has a conventional extension. Insert the object id before the '.' of the extension.
|
// 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());
|
fileName = fileName.substring(0, lastDotIndex) + objectIdSuffix + fileName.substring(lastDotIndex, fileName.length());
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
// The file has no extension or the only '.' in the file is an initial '.', as in a hidden file.
|
// 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 name.
|
// Add the object id to the end of the file tagName.
|
||||||
fileName += objectIdSuffix;
|
fileName += objectIdSuffix;
|
||||||
}
|
}
|
||||||
localFilePath.append(File.separator);
|
localFilePath.append(File.separator);
|
||||||
localFilePath.append(fileName);
|
localFilePath.append(fileName);
|
||||||
|
|
||||||
// If the local file doesn't already exist, create it now.
|
// 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 name to a file.
|
// 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());
|
File localFile = new File(localFilePath.toString());
|
||||||
if (!localFile.exists()) {
|
if (!localFile.exists()) {
|
||||||
ExtractFscContentVisitor.extract(file, localFile, null, null);
|
ExtractFscContentVisitor.extract(file, localFile, null, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add the hyperlink to the row. A column header for it was created in startTable().
|
// Add the hyperlink to the row. A column header for it was created in startTable().
|
||||||
StringBuilder localFileLink = new StringBuilder();
|
StringBuilder localFileLink = new StringBuilder();
|
||||||
localFileLink.append("<a href=\"file:///");
|
localFileLink.append("<a href=\"file:///");
|
||||||
localFileLink.append(localFilePath.toString());
|
localFileLink.append(localFilePath.toString());
|
||||||
localFileLink.append("\">View File</a>");
|
localFileLink.append("\">");
|
||||||
|
localFileLink.append(linkHTMLContent);
|
||||||
|
localFileLink.append("</a>");
|
||||||
row.add(localFileLink.toString());
|
row.add(localFileLink.toString());
|
||||||
|
|
||||||
StringBuilder builder = new StringBuilder();
|
StringBuilder builder = new StringBuilder();
|
||||||
@ -892,4 +947,17 @@ public class ReportHTML implements TableReportModule {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private String prepareThumbnail(AbstractFile file) {
|
||||||
|
File thumbFile = ImageUtils.getIconFile(file, ImageUtils.ICON_SIZE_SMALL);
|
||||||
|
try {
|
||||||
|
File to = new File(thumbsPath);
|
||||||
|
FileUtil.copyFile(FileUtil.toFileObject(thumbFile), FileUtil.toFileObject(to), thumbFile.getName(), "");
|
||||||
|
} catch (IOException ex) {
|
||||||
|
logger.log(Level.SEVERE, "Failed to write thumb file to report directory.");
|
||||||
|
}
|
||||||
|
|
||||||
|
return THUMBS_REL_PATH + thumbFile.getName();
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -33,6 +33,7 @@ import java.util.ArrayList;
|
|||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
import java.util.logging.Level;
|
import java.util.logging.Level;
|
||||||
|
import org.sleuthkit.autopsy.contentviewers.Utilities;
|
||||||
import org.sleuthkit.autopsy.coreutils.Logger;
|
import org.sleuthkit.autopsy.coreutils.Logger;
|
||||||
import org.sleuthkit.autopsy.coreutils.Version;
|
import org.sleuthkit.autopsy.coreutils.Version;
|
||||||
import org.sleuthkit.autopsy.ingest.PipelineContext;
|
import org.sleuthkit.autopsy.ingest.PipelineContext;
|
||||||
@ -197,41 +198,7 @@ public final class ExifParserFileIngestModule extends IngestModuleAbstractFile {
|
|||||||
* @return true if to be processed
|
* @return true if to be processed
|
||||||
*/
|
*/
|
||||||
private boolean parsableFormat(AbstractFile f) {
|
private boolean parsableFormat(AbstractFile f) {
|
||||||
return isJpegFileHeader(f);
|
return Utilities.isJpegFileHeader(f);
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Check if is jpeg file based on header
|
|
||||||
*
|
|
||||||
* @param file
|
|
||||||
*
|
|
||||||
* @return true if jpeg file, false otherwise
|
|
||||||
*/
|
|
||||||
public static boolean isJpegFileHeader(AbstractFile file) {
|
|
||||||
if (file.getSize() < 100) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
byte[] fileHeaderBuffer = new byte[2];
|
|
||||||
int bytesRead;
|
|
||||||
try {
|
|
||||||
bytesRead = file.read(fileHeaderBuffer, 0, 2);
|
|
||||||
} catch (TskCoreException ex) {
|
|
||||||
//ignore if can't read the first few bytes, not a JPEG
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (bytesRead != 2) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
/*
|
|
||||||
* Check for the JPEG header. Since Java bytes are signed, we cast them
|
|
||||||
* to an int first.
|
|
||||||
*/
|
|
||||||
if (((int) (fileHeaderBuffer[0] & 0xff) == 0xff) && ((int) (fileHeaderBuffer[1] & 0xff) == 0xd8)) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
Loading…
x
Reference in New Issue
Block a user