From deaa670c0e9b4b867a843f89dc3ad71162d3ee66 Mon Sep 17 00:00:00 2001 From: "U-BASIS\\dsmyda" Date: Thu, 3 Dec 2020 19:37:06 -0500 Subject: [PATCH 1/2] Improved the icon search algorithm by adding new types --- .../search/DomainSearchThumbnailLoader.java | 69 ++++++++++++++----- 1 file changed, 52 insertions(+), 17 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/discovery/search/DomainSearchThumbnailLoader.java b/Core/src/org/sleuthkit/autopsy/discovery/search/DomainSearchThumbnailLoader.java index 4a17ad6434..fbcc2e2d55 100755 --- a/Core/src/org/sleuthkit/autopsy/discovery/search/DomainSearchThumbnailLoader.java +++ b/Core/src/org/sleuthkit/autopsy/discovery/search/DomainSearchThumbnailLoader.java @@ -22,6 +22,7 @@ import com.google.common.cache.CacheLoader; import java.awt.Image; import java.util.List; import java.util.ArrayList; +import java.util.Arrays; import java.util.Collections; import org.sleuthkit.autopsy.coreutils.ImageUtils; import org.sleuthkit.datamodel.BlackboardArtifact; @@ -47,8 +48,12 @@ import org.openide.util.ImageUtilities; public class DomainSearchThumbnailLoader extends CacheLoader { private static final String UNSUPPORTED_IMAGE = "org/sleuthkit/autopsy/images/image-extraction-not-supported.png"; - private static final String JPG_EXTENSION = "jpg"; - private static final String JPG_MIME_TYPE = "image/jpeg"; + private static final List SUPPORTED_EXTENSIONS = Arrays.asList("jpg", "svg", "png", "webp", "ico", "gif"); + private static final List SUPPORTED_MIMETYPES = Arrays.asList( + "image/gif", "image/jpeg", "image/png", "image/webp", + "image/svg+xml", "image/vnd.microsoft.icon", "image/x-icon"); + private static final String ICO_EXTENSION = "ico"; + private static final List ICO_MIMETYPES = Arrays.asList("image/vnd.microsoft.icon", "image/x-icon"); private final DomainSearchArtifactsCache artifactsCache; /** @@ -75,8 +80,21 @@ public class DomainSearchThumbnailLoader extends CacheLoader webDownloads = artifactsCache.get(webDownloadsRequest); - final List webDownloadPictures = getJpegsFromWebDownload(caseDb, webDownloads); - Collections.sort(webDownloadPictures, (file1, file2) -> Long.compare(file1.getCrtime(), file2.getCrtime())); + final List webDownloadPictures = getCandidatesFromWebDownloads(caseDb, webDownloads); + Collections.sort(webDownloadPictures, (file1, file2) -> { + // Push ICO to the back of the sorted collection, so that ICO + // is a last resort matching type. + if (isIco(file1) && isIco(file2)) { + return Long.compare(file1.getCrtime(), file2.getCrtime()); + } else if (isIco(file1)) { + return 1; + } else if (isIco(file2)) { + return -1; + } else { + return Long.compare(file1.getCrtime(), file2.getCrtime()); + } + }); + for (int i = webDownloadPictures.size() - 1; i >= 0; i--) { if(Thread.currentThread().isInterrupted()) { throw new InterruptedException(); @@ -92,8 +110,20 @@ public class DomainSearchThumbnailLoader extends CacheLoader webCacheArtifacts = artifactsCache.get(webCacheRequest); - final List webCachePictures = getJpegsFromWebCache(caseDb, webCacheArtifacts); - Collections.sort(webCachePictures, (file1, file2) -> Long.compare(file1.getSize(), file2.getSize())); + final List webCachePictures = getCandidatesFromWebCache(caseDb, webCacheArtifacts); + Collections.sort(webCachePictures, (file1, file2) -> { + // Push ICO to the back of the sorted collection, so that ICO + // is a last resort matching type. + if (isIco(file1) && isIco(file2)) { + return Long.compare(file1.getSize(), file2.getSize()); + } else if (isIco(file1)) { + return 1; + } else if (isIco(file2)) { + return -1; + } else { + return Long.compare(file1.getSize(), file2.getSize()); + } + }); for (int i = webCachePictures.size() - 1; i >= 0; i--) { if(Thread.currentThread().isInterrupted()) { throw new InterruptedException(); @@ -119,16 +149,21 @@ public class DomainSearchThumbnailLoader extends CacheLoader getJpegsFromWebDownload(SleuthkitCase caseDb, List artifacts) throws TskCoreException, InterruptedException { - final List jpegs = new ArrayList<>(); + private List getCandidatesFromWebDownloads(SleuthkitCase caseDb, List artifacts) throws TskCoreException, InterruptedException { + final List candidates = new ArrayList<>(); for (BlackboardArtifact artifact : artifacts) { if(Thread.currentThread().isInterrupted()) { throw new InterruptedException(); } final Content sourceContent = caseDb.getContentById(artifact.getObjectID()); - addIfJpeg(jpegs, sourceContent); + addIfSupported(candidates, sourceContent); } - return jpegs; + return candidates; + } + + private boolean isIco(AbstractFile file) { + return ICO_EXTENSION.equals(file.getNameExtension()) + || ICO_MIMETYPES.contains(file.getMIMEType()); } /** @@ -140,9 +175,9 @@ public class DomainSearchThumbnailLoader extends CacheLoader getJpegsFromWebCache(SleuthkitCase caseDb, List artifacts) throws TskCoreException, InterruptedException { + private List getCandidatesFromWebCache(SleuthkitCase caseDb, List artifacts) throws TskCoreException, InterruptedException { final BlackboardAttribute.Type TSK_PATH_ID = new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_PATH_ID); - final List jpegs = new ArrayList<>(); + final List candidates = new ArrayList<>(); for (BlackboardArtifact artifact : artifacts) { if(Thread.currentThread().isInterrupted()) { throw new InterruptedException(); @@ -150,10 +185,10 @@ public class DomainSearchThumbnailLoader extends CacheLoader files, Content sourceContent) { + private void addIfSupported(List files, Content sourceContent) { if ((sourceContent instanceof AbstractFile) && !(sourceContent instanceof DataSource)) { final AbstractFile file = (AbstractFile) sourceContent; - if (JPG_EXTENSION.equals(file.getNameExtension()) - || JPG_MIME_TYPE.equals(file.getMIMEType())) { + if (SUPPORTED_EXTENSIONS.contains(file.getNameExtension()) + || SUPPORTED_MIMETYPES.contains(file.getMIMEType())) { files.add(file); } } From e2a337a9cbce8c62903e12d96668234be05175d6 Mon Sep 17 00:00:00 2001 From: "U-BASIS\\dsmyda" Date: Thu, 3 Dec 2020 19:40:56 -0500 Subject: [PATCH 2/2] Updated comments --- .../search/DomainSearchThumbnailLoader.java | 24 +++++++++---------- 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/discovery/search/DomainSearchThumbnailLoader.java b/Core/src/org/sleuthkit/autopsy/discovery/search/DomainSearchThumbnailLoader.java index fbcc2e2d55..888cc5379b 100755 --- a/Core/src/org/sleuthkit/autopsy/discovery/search/DomainSearchThumbnailLoader.java +++ b/Core/src/org/sleuthkit/autopsy/discovery/search/DomainSearchThumbnailLoader.java @@ -39,9 +39,10 @@ import org.sleuthkit.datamodel.TskCoreException; import org.openide.util.ImageUtilities; /** - * Loads a thumbnail for the given request. Thumbnail candidates are JPEG files - * that have either TSK_WEB_DOWNLOAD or TSK_WEB_CACHE artifacts that match the - * domain name (see the DomainSearch getArtifacts() API). JPEG files are sorted + * Loads a thumbnail for the given request. Thumbnail candidates types are defined below. + * These candidates types must be the source of either TSK_WEB_DOWNLOAD or + * TSK_WEB_CACHE artifacts that match the + * domain name (see the DomainSearch getArtifacts() API). Candidate files are sorted * by most recent if sourced from TSK_WEB_DOWNLOADs and by size if sourced from * TSK_WEB_CACHE artifacts. The first suitable thumbnail is selected. */ @@ -139,12 +140,12 @@ public class DomainSearchThumbnailLoader extends CacheLoader getCandidatesFromWebCache(SleuthkitCase caseDb, List artifacts) throws TskCoreException, InterruptedException { @@ -192,10 +193,9 @@ public class DomainSearchThumbnailLoader extends CacheLoader files, Content sourceContent) {