From df1745dc37244e6226b80aa6420d3a7f6adac88b Mon Sep 17 00:00:00 2001 From: Kelly Kelly Date: Tue, 13 Aug 2019 14:00:27 -0400 Subject: [PATCH 01/24] Added ExtractRecycyleBin module to RA --- .../recentactivity/Bundle.properties-MERGED | 9 +- .../recentactivity/ExtractRecycleBin.java | 279 ++++++++++++++++++ .../recentactivity/RAImageIngestModule.java | 2 + .../autopsy/recentactivity/Util.java | 18 ++ 4 files changed, 301 insertions(+), 7 deletions(-) create mode 100755 RecentActivity/src/org/sleuthkit/autopsy/recentactivity/ExtractRecycleBin.java diff --git a/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/Bundle.properties-MERGED b/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/Bundle.properties-MERGED index 5e11018086..40771a0d41 100755 --- a/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/Bundle.properties-MERGED +++ b/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/Bundle.properties-MERGED @@ -2,14 +2,9 @@ cannotBuildXmlParser=Unable to build XML parser: cannotLoadSEUQA=Unable to load Search Engine URL Query Analyzer settings file, SEUQAMappings.xml: cannotParseXml=Unable to parse XML file: ChromeCacheExtractor.moduleName=ChromeCacheExtractor -# {0} - module name -# {1} - row number -# {2} - table length -# {3} - cache path ChromeCacheExtractor.progressMsg={0}: Extracting cache entry {1} of {2} entries from {3} DataSourceUsage_AndroidMedia=Android Media Card DataSourceUsage_FlashDrive=Flash Drive -# {0} - OS name DataSourceUsageAnalyzer.customVolume.label=OS Drive ({0}) DataSourceUsageAnalyzer.parentModuleName=Recent Activity Extract.indexError.message=Failed to index artifact for keyword search. @@ -51,6 +46,7 @@ ExtractOs.windowsVolume.label=OS Drive (Windows) ExtractOs.yellowDogLinuxOs.label=Linux (Yellow Dog) ExtractOs.yellowDogLinuxVolume.label=OS Drive (Linux Yellow Dog) ExtractOS_progressMessage=Checking for OS +ExtractRecycleBin_module_name=Recycle Bin ExtractSafari_Error_Getting_History=An error occurred while processing Safari history files. ExtractSafari_Error_Parsing_Bookmark=An error occured while processing Safari Bookmark files ExtractSafari_Error_Parsing_Cookies=An error occured while processing Safari Cookies files @@ -64,7 +60,7 @@ ExtractZone_progress_Msg=Extracting :Zone.Identifer files ExtractZone_Restricted=Restricted Sites Zone ExtractZone_Trusted=Trusted Sites Zone OpenIDE-Module-Display-Category=Ingest Module -OpenIDE-Module-Long-Description=Recent Activity ingest module.\n\n\The module extracts useful information about the recent user activity on the disk image being ingested, such as:\n\n- Recently open documents,\n- Web activity (sites visited, stored cookies, book marked sites, search engine queries, file downloads),\n- Recently attached devices,\n- Installed programs.\n\nThe module currently supports Windows only disk images.\nThe plugin is also fully functional when deployed on Windows version of Autopsy. +OpenIDE-Module-Long-Description=Recent Activity ingest module.\n\nThe module extracts useful information about the recent user activity on the disk image being ingested, such as:\n\n- Recently open documents,\n- Web activity (sites visited, stored cookies, book marked sites, search engine queries, file downloads),\n- Recently attached devices,\n- Installed programs.\n\nThe module currently supports Windows only disk images.\nThe plugin is also fully functional when deployed on Windows version of Autopsy. OpenIDE-Module-Name=RecentActivity OpenIDE-Module-Short-Description=Recent Activity finder ingest module Chrome.moduleName=Chrome @@ -187,7 +183,6 @@ RecentDocumentsByLnk.parentModuleName.noSpace=RecentActivity RecentDocumentsByLnk.parentModuleName=Recent Activity RegRipperFullNotFound=Full version RegRipper executable not found. RegRipperNotFound=Autopsy RegRipper executable not found. -# {0} - file name SearchEngineURLQueryAnalyzer.init.exception.msg=Unable to find {0}. SearchEngineURLQueryAnalyzer.moduleName.text=Search Engine SearchEngineURLQueryAnalyzer.engineName.none=NONE diff --git a/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/ExtractRecycleBin.java b/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/ExtractRecycleBin.java new file mode 100755 index 0000000000..10df98ae4c --- /dev/null +++ b/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/ExtractRecycleBin.java @@ -0,0 +1,279 @@ +/* + * + * Autopsy Forensic Browser + * + * Copyright 2019 Basis Technology Corp. + * + * Copyright 2012 42six Solutions. + * Contact: aebadirad 42six com + * Project Contact/Architect: carrier sleuthkit 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.recentactivity; + +import java.io.File; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.nio.ByteBuffer; +import java.nio.ByteOrder; +import java.nio.file.Files; +import java.nio.file.Paths; +import java.util.Arrays; +import java.util.List; +import java.util.logging.Level; +import org.openide.util.NbBundle.Messages; +import org.sleuthkit.autopsy.casemodule.Case; +import org.sleuthkit.autopsy.casemodule.services.FileManager; +import org.sleuthkit.autopsy.coreutils.Logger; +import org.sleuthkit.autopsy.datamodel.ContentUtils; +import org.sleuthkit.autopsy.ingest.DataSourceIngestModuleProgress; +import org.sleuthkit.autopsy.ingest.IngestJobContext; +import org.sleuthkit.datamodel.AbstractFile; +import org.sleuthkit.datamodel.BlackboardArtifact; +import org.sleuthkit.datamodel.BlackboardAttribute; +import static org.sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DATETIME_DELETED; +import static org.sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE.TSK_PATH; +import org.sleuthkit.datamodel.Content; +import org.sleuthkit.datamodel.SleuthkitCase; +import org.sleuthkit.datamodel.TskCoreException; +import org.sleuthkit.datamodel.TskDataException; + +/** + * This module is based on the RecycleBin python module from Mark Mackinnon. + * + * @see + * Recycle_Bin.py + * + */ +final class ExtractRecycleBin extends Extract { + + private static final Logger logger = Logger.getLogger(ExtractRecycleBin.class.getName()); + + private static final String RECYCLE_BIN_ARTIFACT_NAME = "TSK_RECYCLE_BIN"; //NON-NLS + + private static final int V1_FILE_NAME_OFFSET = 24; + private static final int V2_FILE_NAME_OFFSET = 28; + + @Messages({ + "ExtractRecycleBin_module_name=Recycle Bin" + }) + ExtractRecycleBin() { + this.moduleName = Bundle.ExtractRecycleBin_module_name(); + } + + @Override + void process(Content dataSource, IngestJobContext context, DataSourceIngestModuleProgress progressBar) { + FileManager fileManager = Case.getCurrentCase().getServices().getFileManager(); + String tempDirPath = RAImageIngestModule.getRATempPath(Case.getCurrentCase(), "recyclebin"); //NON-NLS + SleuthkitCase skCase = Case.getCurrentCase().getSleuthkitCase(); + + // At this time it was decided tjat we would not include TSK_RECYCLE_BIN + // in the default list of BlackboardArtifact types. + try { + skCase.addBlackboardArtifactType(RECYCLE_BIN_ARTIFACT_NAME, "Recycle Bin"); //NON-NLS + } catch (TskCoreException ex) { + logger.log(Level.WARNING, String.format("%s may not have been created.", RECYCLE_BIN_ARTIFACT_NAME), ex); + } catch (TskDataException ex) { + logger.log(Level.WARNING, String.format("%s may have already been defined for this case", RECYCLE_BIN_ARTIFACT_NAME), ex); + } + + BlackboardArtifact.Type recycleBinArtifactType; + + try { + recycleBinArtifactType = skCase.getArtifactType(RECYCLE_BIN_ARTIFACT_NAME); + } catch (TskCoreException ex) { + logger.log(Level.WARNING, String.format("Unable to retrive custom artifact type %s", RECYCLE_BIN_ARTIFACT_NAME), ex); // NON-NLS + // If this doesn't work bail. + return; + } + + List iFiles; + + try { + iFiles = fileManager.findFiles(dataSource, "$I%"); //NON-NLS + } catch (TskCoreException ex) { + logger.log(Level.WARNING, "Unable to find recycle bin I files.", ex); //NON-NLS + return; // No need to continue + } + + for (AbstractFile iFile : iFiles) { + + if (context.dataSourceIngestIsCancelled()) { + return; + } + + String tempFilePath = tempDirPath + File.separator + iFile.getName(); + + try { + try { + ContentUtils.writeToFile(iFile, new File(tempFilePath)); + } catch (IOException ex) { + logger.log(Level.WARNING, String.format("Unable to write %s to temp directory. File name: %s", iFile.getName(), tempFilePath), ex); //NON-NLS + // if we cannot make a copy of the $I file for later processing + // move onto the next file + continue; + } + + RecycledFileMetaData metaData; + try { + metaData = parseIFile(tempFilePath); + } catch (IOException ex) { + logger.log(Level.WARNING, String.format("Unable to parse iFile %s", iFile.getName()), ex); //NON-NLS + // Unable to parse the $I file move onto the next file + continue; + } + + String rFileName = iFile.getName().replace("$I", "$R"); //NON-NLS + List rFiles; + + try { + rFiles = fileManager.findFiles(dataSource, rFileName, iFile.getParentPath()); + } catch (TskCoreException ex) { + logger.log(Level.WARNING, String.format("Unable to find R file (%s) for I file (%s)", rFileName, iFile.getName()), ex); //NON-NLS + // If there are no $R files go on to the next $I file + continue; + } + + for (AbstractFile rFile : rFiles) { + if (context.dataSourceIngestIsCancelled()) { + return; + } + + if (iFile.getParentPath().equals(rFile.getParentPath())) { + try { + BlackboardArtifact bba = rFile.newArtifact(recycleBinArtifactType.getTypeID()); + bba.addAttribute(new BlackboardAttribute(TSK_PATH, getName(), metaData.getFileName())); + bba.addAttribute(new BlackboardAttribute(TSK_DATETIME_DELETED, getName(), metaData.getDeletedTimeStamp())); + + postArtifact(bba); + } catch (TskCoreException ex) { + logger.log(Level.WARNING, String.format("Unable to add attributes to artifact %s", rFile.getName()), ex); //NON-NLS + } + } + } + } finally { + (new File(tempFilePath)).delete(); + } + } + + (new File(tempDirPath)).delete(); + } + + /** + * Parse the $I file. + * + * File format prior to Windows 10: + * + * + * + * + * + * + *
OffsetSizeDescription
08Header
88File Size
168Deleted Timestamp
24520File Name
+ * + * File format Windows 10+ + * + * + * + * + * + * + * + *
OffsetSizeDescription
08Header
88File Size
168Deleted TimeStamp
244File Name Length
28varFile Name
+ * + * For versions of Windows prior to 10, header = 0x01. Windows 10+ header == + * 0x02 + * + * @param iFilePath + * + * @throws FileNotFoundException + * @throws IOException + */ + RecycledFileMetaData parseIFile(String iFilePath) throws FileNotFoundException, IOException { + byte[] allBytes = Files.readAllBytes(Paths.get(iFilePath)); + + ByteBuffer byteBuffer = ByteBuffer.wrap(allBytes); + byteBuffer.order(ByteOrder.LITTLE_ENDIAN); + + long version = byteBuffer.getLong(); + long fileSize = byteBuffer.getLong(); + long timestamp = byteBuffer.getLong(); + + // Convert from windows FILETIME to Unix Epoch seconds + timestamp = Util.filetimeToMillis(timestamp) / 1000; + + byte[] stringBytes; + + if (version == 1) { + stringBytes = Arrays.copyOfRange(allBytes, V1_FILE_NAME_OFFSET, allBytes.length); + } else { + int fileNameLength = byteBuffer.getInt(); + stringBytes = Arrays.copyOfRange(allBytes, V2_FILE_NAME_OFFSET, fileNameLength); + } + + String fileName = new String(stringBytes, "UTF-16LE"); //NON-NLS + + return new RecycledFileMetaData(fileSize, timestamp, fileName); + } + + /** + * Stores the data from the $I files. + */ + final class RecycledFileMetaData { + + private final long fileSize; + private final long deletedTimeStamp; + private final String fileName; + + /** + * Constructs a new instance. + * + * @param fileSize Size of the deleted file. + * @param deletedTimeStamp Time the file was deleted. + * @param fileName Name of the deleted file. + */ + RecycledFileMetaData(Long fileSize, long deletedTimeStamp, String fileName) { + this.fileSize = fileSize; + this.deletedTimeStamp = deletedTimeStamp; + this.fileName = fileName; + } + + /** + * Returns the size of the recycled file. + * + * @return Size of deleted file + */ + long getFileSize() { + return fileSize; + } + + /** + * Returns the time the file was deleted. + * + * @return deleted time in epoch seconds. + */ + long getDeletedTimeStamp() { + return deletedTimeStamp; + } + + /** + * Returns the name of the deleted file. + * + * @return String name of the deleted file + */ + String getFileName() { + return fileName; + } + } +} diff --git a/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/RAImageIngestModule.java b/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/RAImageIngestModule.java index db815e9274..a52b5b65e1 100644 --- a/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/RAImageIngestModule.java +++ b/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/RAImageIngestModule.java @@ -77,6 +77,7 @@ public final class RAImageIngestModule implements DataSourceIngestModule { Extract dataSourceAnalyzer = new DataSourceUsageAnalyzer(); Extract safari = new ExtractSafari(); Extract zoneInfo = new ExtractZoneIdentifier(); + Extract recycleBin = new ExtractRecycleBin(); extractors.add(chrome); extractors.add(firefox); @@ -84,6 +85,7 @@ public final class RAImageIngestModule implements DataSourceIngestModule { extractors.add(edge); extractors.add(safari); extractors.add(recentDocuments); + extractors.add(recycleBin); extractors.add(SEUQA); // this needs to run after the web browser modules extractors.add(registry); // this should run after quicker modules like the browser modules and needs to run before the DataSourceUsageAnalyzer extractors.add(osExtract); // this needs to run before the DataSourceUsageAnalyzer diff --git a/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/Util.java b/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/Util.java index a6c6416416..ff95c60ca8 100644 --- a/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/Util.java +++ b/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/Util.java @@ -51,6 +51,12 @@ import org.sleuthkit.datamodel.TskCoreException; class Util { private static Logger logger = Logger.getLogger(Util.class.getName()); + + /** Difference between Filetime epoch and Unix epoch (in ms). */ + private static final long FILETIME_EPOCH_DIFF = 11644473600000L; + + /** One millisecond expressed in units of 100s of nanoseconds. */ + private static final long FILETIME_ONE_MILLISECOND = 10 * 1000; private Util() { } @@ -176,4 +182,16 @@ class Util { } return results; } + + /** + * Converts a windows FILETIME to java-unix epoch milliseconds + * + * @param filetime 100 nanosecond intervals from jan 1, 1601 + * + * @return java-unix epoch milliseconds + */ + static long filetimeToMillis(final long filetime) { + return (filetime / FILETIME_ONE_MILLISECOND) - FILETIME_EPOCH_DIFF; + } + } From fa9db11e0c248fc8c940afa6c936e47bcc241d29 Mon Sep 17 00:00:00 2001 From: Kelly Kelly Date: Tue, 13 Aug 2019 14:26:06 -0400 Subject: [PATCH 02/24] Fixed typo --- .../org/sleuthkit/autopsy/recentactivity/ExtractRecycleBin.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/ExtractRecycleBin.java b/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/ExtractRecycleBin.java index 10df98ae4c..fe32281fff 100755 --- a/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/ExtractRecycleBin.java +++ b/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/ExtractRecycleBin.java @@ -50,7 +50,7 @@ import org.sleuthkit.datamodel.TskCoreException; import org.sleuthkit.datamodel.TskDataException; /** - * This module is based on the RecycleBin python module from Mark Mackinnon. + * This module is based on the RecycleBin python module from Mark McKinnon. * * @see * Recycle_Bin.py From ec4803309523cda4cd30dbf5eb925bfd10f3c485 Mon Sep 17 00:00:00 2001 From: Kelly Kelly Date: Wed, 14 Aug 2019 10:56:11 -0400 Subject: [PATCH 03/24] Added support for usernames --- .../recentactivity/ExtractRecycleBin.java | 65 ++++++++++++++++--- .../recentactivity/RAImageIngestModule.java | 2 +- 2 files changed, 57 insertions(+), 10 deletions(-) diff --git a/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/ExtractRecycleBin.java b/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/ExtractRecycleBin.java index fe32281fff..4cbcad3b62 100755 --- a/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/ExtractRecycleBin.java +++ b/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/ExtractRecycleBin.java @@ -30,7 +30,9 @@ import java.nio.ByteOrder; import java.nio.file.Files; import java.nio.file.Paths; import java.util.Arrays; +import java.util.HashMap; import java.util.List; +import java.util.Map; import java.util.logging.Level; import org.openide.util.NbBundle.Messages; import org.sleuthkit.autopsy.casemodule.Case; @@ -41,11 +43,13 @@ import org.sleuthkit.autopsy.ingest.DataSourceIngestModuleProgress; import org.sleuthkit.autopsy.ingest.IngestJobContext; import org.sleuthkit.datamodel.AbstractFile; import org.sleuthkit.datamodel.BlackboardArtifact; +import static org.sleuthkit.datamodel.BlackboardArtifact.ARTIFACT_TYPE.TSK_OS_ACCOUNT; import org.sleuthkit.datamodel.BlackboardAttribute; import static org.sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DATETIME_DELETED; import static org.sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE.TSK_PATH; +import static org.sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE.TSK_USER_ID; +import static org.sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE.TSK_USER_NAME; import org.sleuthkit.datamodel.Content; -import org.sleuthkit.datamodel.SleuthkitCase; import org.sleuthkit.datamodel.TskCoreException; import org.sleuthkit.datamodel.TskDataException; @@ -76,27 +80,36 @@ final class ExtractRecycleBin extends Extract { void process(Content dataSource, IngestJobContext context, DataSourceIngestModuleProgress progressBar) { FileManager fileManager = Case.getCurrentCase().getServices().getFileManager(); String tempDirPath = RAImageIngestModule.getRATempPath(Case.getCurrentCase(), "recyclebin"); //NON-NLS - SleuthkitCase skCase = Case.getCurrentCase().getSleuthkitCase(); - - // At this time it was decided tjat we would not include TSK_RECYCLE_BIN + + // At this time it was decided that we would not include TSK_RECYCLE_BIN // in the default list of BlackboardArtifact types. try { - skCase.addBlackboardArtifactType(RECYCLE_BIN_ARTIFACT_NAME, "Recycle Bin"); //NON-NLS + tskCase.addBlackboardArtifactType(RECYCLE_BIN_ARTIFACT_NAME, "Recycle Bin"); //NON-NLS } catch (TskCoreException ex) { logger.log(Level.WARNING, String.format("%s may not have been created.", RECYCLE_BIN_ARTIFACT_NAME), ex); } catch (TskDataException ex) { - logger.log(Level.WARNING, String.format("%s may have already been defined for this case", RECYCLE_BIN_ARTIFACT_NAME), ex); + logger.log(Level.INFO, String.format("%s may have already been defined for this case", RECYCLE_BIN_ARTIFACT_NAME)); } BlackboardArtifact.Type recycleBinArtifactType; try { - recycleBinArtifactType = skCase.getArtifactType(RECYCLE_BIN_ARTIFACT_NAME); + recycleBinArtifactType = tskCase.getArtifactType(RECYCLE_BIN_ARTIFACT_NAME); } catch (TskCoreException ex) { logger.log(Level.WARNING, String.format("Unable to retrive custom artifact type %s", RECYCLE_BIN_ARTIFACT_NAME), ex); // NON-NLS // If this doesn't work bail. return; } + Map userNameMap; + + try { + userNameMap = makeUserNameMap(dataSource); + } catch (TskCoreException ex) { + logger.log(Level.WARNING, "Unable to create OS Account user name map", ex); + // This is not the end of the world we will just continue without + // user names + userNameMap = new HashMap<>(); + } List iFiles; @@ -135,6 +148,9 @@ final class ExtractRecycleBin extends Extract { } String rFileName = iFile.getName().replace("$I", "$R"); //NON-NLS + String userID = getUserIDFromPath(iFile.getParentPath()); + String userName = userNameMap.get(userID); + List rFiles; try { @@ -155,6 +171,7 @@ final class ExtractRecycleBin extends Extract { BlackboardArtifact bba = rFile.newArtifact(recycleBinArtifactType.getTypeID()); bba.addAttribute(new BlackboardAttribute(TSK_PATH, getName(), metaData.getFileName())); bba.addAttribute(new BlackboardAttribute(TSK_DATETIME_DELETED, getName(), metaData.getDeletedTimeStamp())); + bba.addAttribute(new BlackboardAttribute(TSK_USER_NAME, getName(), userName != null ? userName : "")); postArtifact(bba); } catch (TskCoreException ex) { @@ -218,14 +235,44 @@ final class ExtractRecycleBin extends Extract { if (version == 1) { stringBytes = Arrays.copyOfRange(allBytes, V1_FILE_NAME_OFFSET, allBytes.length); } else { - int fileNameLength = byteBuffer.getInt(); - stringBytes = Arrays.copyOfRange(allBytes, V2_FILE_NAME_OFFSET, fileNameLength); + int fileNameLength = byteBuffer.getInt() * 2; //Twice the bytes for unicode + stringBytes = Arrays.copyOfRange(allBytes, V2_FILE_NAME_OFFSET, V2_FILE_NAME_OFFSET + fileNameLength); } String fileName = new String(stringBytes, "UTF-16LE"); //NON-NLS return new RecycledFileMetaData(fileSize, timestamp, fileName); } + + + private Map makeUserNameMap(Content dataSource) throws TskCoreException{ + Map userNameMap = new HashMap<>(); + + List accounts = blackboard.getArtifacts(TSK_OS_ACCOUNT.getTypeID(), dataSource.getId()); + + for (BlackboardArtifact account: accounts) { + BlackboardAttribute nameAttribute = getAttributeForArtifact(account, TSK_USER_NAME); + BlackboardAttribute idAttribute = getAttributeForArtifact(account, TSK_USER_ID); + + String userName = nameAttribute != null ? nameAttribute.getDisplayString() : ""; + String userID = idAttribute != null ? idAttribute.getDisplayString() : ""; + + if (!userID.isEmpty()) { + userNameMap.put(userID, userName); + } + } + + return userNameMap; + } + + private String getUserIDFromPath(String iFileParentPath) { + int index = iFileParentPath.indexOf("-") - 1; + return (iFileParentPath.substring(index)).replace("/", ""); + } + + private BlackboardAttribute getAttributeForArtifact(BlackboardArtifact artifact, BlackboardAttribute.ATTRIBUTE_TYPE type) throws TskCoreException{ + return artifact.getAttribute(new BlackboardAttribute.Type(BlackboardAttribute.ATTRIBUTE_TYPE.fromID(type.getTypeID()))); + } /** * Stores the data from the $I files. diff --git a/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/RAImageIngestModule.java b/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/RAImageIngestModule.java index a52b5b65e1..444a6d638d 100644 --- a/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/RAImageIngestModule.java +++ b/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/RAImageIngestModule.java @@ -85,12 +85,12 @@ public final class RAImageIngestModule implements DataSourceIngestModule { extractors.add(edge); extractors.add(safari); extractors.add(recentDocuments); - extractors.add(recycleBin); extractors.add(SEUQA); // this needs to run after the web browser modules extractors.add(registry); // this should run after quicker modules like the browser modules and needs to run before the DataSourceUsageAnalyzer extractors.add(osExtract); // this needs to run before the DataSourceUsageAnalyzer extractors.add(dataSourceAnalyzer); //this needs to run after ExtractRegistry and ExtractOs extractors.add(zoneInfo); // this needs to run after the web browser modules + extractors.add(recycleBin); // this needs to run after ExtractRegistry and ExtractOS browserExtractors.add(chrome); browserExtractors.add(firefox); From e1599ecb9a6d5bc48359c1d37fa22c7de47458d2 Mon Sep 17 00:00:00 2001 From: Kelly Kelly Date: Thu, 15 Aug 2019 10:03:40 -0400 Subject: [PATCH 04/24] Refactored to hopefully make codacy happy --- .../recentactivity/ExtractRecycleBin.java | 211 ++++++++++++------ 1 file changed, 143 insertions(+), 68 deletions(-) diff --git a/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/ExtractRecycleBin.java b/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/ExtractRecycleBin.java index 4cbcad3b62..08641a164e 100755 --- a/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/ExtractRecycleBin.java +++ b/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/ExtractRecycleBin.java @@ -78,17 +78,12 @@ final class ExtractRecycleBin extends Extract { @Override void process(Content dataSource, IngestJobContext context, DataSourceIngestModuleProgress progressBar) { - FileManager fileManager = Case.getCurrentCase().getServices().getFileManager(); - String tempDirPath = RAImageIngestModule.getRATempPath(Case.getCurrentCase(), "recyclebin"); //NON-NLS - // At this time it was decided that we would not include TSK_RECYCLE_BIN // in the default list of BlackboardArtifact types. try { - tskCase.addBlackboardArtifactType(RECYCLE_BIN_ARTIFACT_NAME, "Recycle Bin"); //NON-NLS + createRecycleBinArtifactType(); } catch (TskCoreException ex) { logger.log(Level.WARNING, String.format("%s may not have been created.", RECYCLE_BIN_ARTIFACT_NAME), ex); - } catch (TskDataException ex) { - logger.log(Level.INFO, String.format("%s may have already been defined for this case", RECYCLE_BIN_ARTIFACT_NAME)); } BlackboardArtifact.Type recycleBinArtifactType; @@ -110,7 +105,8 @@ final class ExtractRecycleBin extends Extract { // user names userNameMap = new HashMap<>(); } - + + FileManager fileManager = Case.getCurrentCase().getServices().getFileManager(); List iFiles; try { @@ -119,72 +115,90 @@ final class ExtractRecycleBin extends Extract { logger.log(Level.WARNING, "Unable to find recycle bin I files.", ex); //NON-NLS return; // No need to continue } + + String tempRARecycleBinPath = RAImageIngestModule.getRATempPath(Case.getCurrentCase(), "recyclebin"); //NON-NLS for (AbstractFile iFile : iFiles) { if (context.dataSourceIngestIsCancelled()) { return; } - - String tempFilePath = tempDirPath + File.separator + iFile.getName(); - - try { - try { - ContentUtils.writeToFile(iFile, new File(tempFilePath)); - } catch (IOException ex) { - logger.log(Level.WARNING, String.format("Unable to write %s to temp directory. File name: %s", iFile.getName(), tempFilePath), ex); //NON-NLS - // if we cannot make a copy of the $I file for later processing - // move onto the next file - continue; - } - - RecycledFileMetaData metaData; - try { - metaData = parseIFile(tempFilePath); - } catch (IOException ex) { - logger.log(Level.WARNING, String.format("Unable to parse iFile %s", iFile.getName()), ex); //NON-NLS - // Unable to parse the $I file move onto the next file - continue; - } - - String rFileName = iFile.getName().replace("$I", "$R"); //NON-NLS - String userID = getUserIDFromPath(iFile.getParentPath()); - String userName = userNameMap.get(userID); - - List rFiles; - - try { - rFiles = fileManager.findFiles(dataSource, rFileName, iFile.getParentPath()); - } catch (TskCoreException ex) { - logger.log(Level.WARNING, String.format("Unable to find R file (%s) for I file (%s)", rFileName, iFile.getName()), ex); //NON-NLS - // If there are no $R files go on to the next $I file - continue; - } - - for (AbstractFile rFile : rFiles) { - if (context.dataSourceIngestIsCancelled()) { - return; - } - - if (iFile.getParentPath().equals(rFile.getParentPath())) { - try { - BlackboardArtifact bba = rFile.newArtifact(recycleBinArtifactType.getTypeID()); - bba.addAttribute(new BlackboardAttribute(TSK_PATH, getName(), metaData.getFileName())); - bba.addAttribute(new BlackboardAttribute(TSK_DATETIME_DELETED, getName(), metaData.getDeletedTimeStamp())); - bba.addAttribute(new BlackboardAttribute(TSK_USER_NAME, getName(), userName != null ? userName : "")); - - postArtifact(bba); - } catch (TskCoreException ex) { - logger.log(Level.WARNING, String.format("Unable to add attributes to artifact %s", rFile.getName()), ex); //NON-NLS - } - } - } - } finally { - (new File(tempFilePath)).delete(); - } + + processIFiles(dataSource, context, recycleBinArtifactType, iFile, userNameMap, tempRARecycleBinPath); } - (new File(tempDirPath)).delete(); + (new File(tempRARecycleBinPath)).delete(); + } + + /** + * Process each individual iFile. + * + * @param dataSource + * @param context + * @param recycleBinArtifactType Module created artifact type + * @param iFile The AbstractFile to process + * @param userNameMap Map of user ids to names + * @param tempRARecycleBinPath Temp directory path + */ + private void processIFiles(Content dataSource, IngestJobContext context, BlackboardArtifact.Type recycleBinArtifactType, AbstractFile iFile, Map userNameMap, String tempRARecycleBinPath) { + String tempFilePath = tempRARecycleBinPath + File.separator + iFile.getName(); + FileManager fileManager = Case.getCurrentCase().getServices().getFileManager(); + try { + try { + ContentUtils.writeToFile(iFile, new File(tempFilePath)); + } catch (IOException ex) { + logger.log(Level.WARNING, String.format("Unable to write %s to temp directory. File name: %s", iFile.getName(), tempFilePath), ex); //NON-NLS + // if we cannot make a copy of the $I file for later processing + // move onto the next file + return; + } + + RecycledFileMetaData metaData; + try { + metaData = parseIFile(tempFilePath); + } catch (IOException ex) { + logger.log(Level.WARNING, String.format("Unable to parse iFile %s", iFile.getName()), ex); //NON-NLS + // Unable to parse the $I file move onto the next file + return; + } + + String rFileName = iFile.getName().replace("$I", "$R"); //NON-NLS + String userID = getUserIDFromPath(iFile.getParentPath()); + String userName = ""; + if (!userID.isEmpty()) { + userName = userNameMap.get(userID); + } else { + // If the iFile doesn't have a user ID in its parent + // directory structure then it is not from the recyle bin + return; + } + + List rFiles; + + try { + rFiles = fileManager.findFiles(dataSource, rFileName, iFile.getParentPath()); + } catch (TskCoreException ex) { + logger.log(Level.WARNING, String.format("Unable to find R file (%s) for I file (%s)", rFileName, iFile.getName()), ex); //NON-NLS + // If there are no $R files go on to the next $I file + return; + } + + for (AbstractFile rFile : rFiles) { + if (context.dataSourceIngestIsCancelled()) { + return; + } + + if (iFile.getParentPath().equals(rFile.getParentPath())) { + try { + postArtifact(createArtifact(rFile, recycleBinArtifactType, metaData.getFileName(), userName, metaData.getDeletedTimeStamp())); + } catch (TskCoreException ex) { + logger.log(Level.WARNING, String.format("Unable to add attributes to artifact %s", rFile.getName()), ex); //NON-NLS + } + } + } + } finally { + (new File(tempFilePath)).delete(); + } } /** @@ -217,7 +231,7 @@ final class ExtractRecycleBin extends Extract { * @throws FileNotFoundException * @throws IOException */ - RecycledFileMetaData parseIFile(String iFilePath) throws FileNotFoundException, IOException { + private RecycledFileMetaData parseIFile(String iFilePath) throws FileNotFoundException, IOException { byte[] allBytes = Files.readAllBytes(Paths.get(iFilePath)); ByteBuffer byteBuffer = ByteBuffer.wrap(allBytes); @@ -244,7 +258,15 @@ final class ExtractRecycleBin extends Extract { return new RecycledFileMetaData(fileSize, timestamp, fileName); } - + /** + * Create a map of userids to usernames from the OS Accounts. + * + * @param dataSource + * + * @return A Map of userIDs and userNames + * + * @throws TskCoreException + */ private Map makeUserNameMap(Content dataSource) throws TskCoreException{ Map userNameMap = new HashMap<>(); @@ -265,14 +287,67 @@ final class ExtractRecycleBin extends Extract { return userNameMap; } + /** + * Helper functions to get the user ID from the iFile parent path. User ids + * will be of the form S-. + * + * @param iFileParentPath String parent path of the iFile + * + * @return String user id + */ private String getUserIDFromPath(String iFileParentPath) { int index = iFileParentPath.indexOf("-") - 1; - return (iFileParentPath.substring(index)).replace("/", ""); + if (index >= 0) { + return (iFileParentPath.substring(index)).replace("/", ""); + } else { + return ""; + } } + /** + * Gets the attribute for the given type from the given artifact. + * + * @param artifact BlackboardArtifact to get the attribute from + * @param type The BlackboardAttribute Type to get + * + * @return BlackboardAttribute for given artifact and type + * + * @throws TskCoreException + */ private BlackboardAttribute getAttributeForArtifact(BlackboardArtifact artifact, BlackboardAttribute.ATTRIBUTE_TYPE type) throws TskCoreException{ return artifact.getAttribute(new BlackboardAttribute.Type(BlackboardAttribute.ATTRIBUTE_TYPE.fromID(type.getTypeID()))); } + + private void createRecycleBinArtifactType() throws TskCoreException { + try { + tskCase.addBlackboardArtifactType(RECYCLE_BIN_ARTIFACT_NAME, "Recycle Bin"); //NON-NLS + } catch (TskDataException ex) { + logger.log(Level.INFO, String.format("%s may have already been defined for this case", RECYCLE_BIN_ARTIFACT_NAME)); + } + + } + + /** + * Create the new artifact for the give rFile + * + * @param rFile AbstractFile to create the artifact for + * @param type Type of artifact to create + * @param fileName The original path of the deleted file + * @param userName The name of the user that deleted the file + * @param dateTime The time in epoch seconds that the file was deleted + * + * @return Newly created artifact + * + * @throws TskCoreException + */ + private BlackboardArtifact createArtifact(AbstractFile rFile, BlackboardArtifact.Type type, String fileName, String userName, long dateTime) throws TskCoreException{ + BlackboardArtifact bba = rFile.newArtifact(type.getTypeID()); + bba.addAttribute(new BlackboardAttribute(TSK_PATH, getName(), fileName)); + bba.addAttribute(new BlackboardAttribute(TSK_DATETIME_DELETED, getName(), dateTime)); + bba.addAttribute(new BlackboardAttribute(TSK_USER_NAME, getName(), userName == null || userName.isEmpty() ? "" : userName)); + + return bba; + } /** * Stores the data from the $I files. From 5721f3c7d4a150c1b869bff679573eab5f35f5c6 Mon Sep 17 00:00:00 2001 From: Kelly Kelly Date: Thu, 15 Aug 2019 10:27:09 -0400 Subject: [PATCH 05/24] merged in changes from other branch --- .../recentactivity/ExtractRecycleBin.java | 53 ++++++++++++++----- 1 file changed, 41 insertions(+), 12 deletions(-) diff --git a/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/ExtractRecycleBin.java b/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/ExtractRecycleBin.java index 08641a164e..3a34fd82bb 100755 --- a/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/ExtractRecycleBin.java +++ b/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/ExtractRecycleBin.java @@ -29,6 +29,7 @@ import java.nio.ByteBuffer; import java.nio.ByteOrder; import java.nio.file.Files; import java.nio.file.Paths; +import java.util.ArrayList; import java.util.Arrays; import java.util.HashMap; import java.util.List; @@ -107,6 +108,15 @@ final class ExtractRecycleBin extends Extract { } FileManager fileManager = Case.getCurrentCase().getServices().getFileManager(); + + Map> rFileMap; + try { + rFileMap = makeRFileMap(dataSource); + } catch (TskCoreException ex) { + logger.log(Level.WARNING, String.format("Unable to create $R file map for dataSource: %s", dataSource.getName()), ex); + return; // No $R files, no need to continue; + } + List iFiles; try { @@ -124,7 +134,7 @@ final class ExtractRecycleBin extends Extract { return; } - processIFiles(dataSource, context, recycleBinArtifactType, iFile, userNameMap, tempRARecycleBinPath); + processIFiles(context, recycleBinArtifactType, iFile, userNameMap, rFileMap, tempRARecycleBinPath); } (new File(tempRARecycleBinPath)).delete(); @@ -140,9 +150,8 @@ final class ExtractRecycleBin extends Extract { * @param userNameMap Map of user ids to names * @param tempRARecycleBinPath Temp directory path */ - private void processIFiles(Content dataSource, IngestJobContext context, BlackboardArtifact.Type recycleBinArtifactType, AbstractFile iFile, Map userNameMap, String tempRARecycleBinPath) { + private void processIFiles(IngestJobContext context, BlackboardArtifact.Type recycleBinArtifactType, AbstractFile iFile, Map userNameMap, Map> rFileMap, String tempRARecycleBinPath) { String tempFilePath = tempRARecycleBinPath + File.separator + iFile.getName(); - FileManager fileManager = Case.getCurrentCase().getServices().getFileManager(); try { try { ContentUtils.writeToFile(iFile, new File(tempFilePath)); @@ -173,15 +182,7 @@ final class ExtractRecycleBin extends Extract { return; } - List rFiles; - - try { - rFiles = fileManager.findFiles(dataSource, rFileName, iFile.getParentPath()); - } catch (TskCoreException ex) { - logger.log(Level.WARNING, String.format("Unable to find R file (%s) for I file (%s)", rFileName, iFile.getName()), ex); //NON-NLS - // If there are no $R files go on to the next $I file - return; - } + List rFiles = rFileMap.get(rFileName); for (AbstractFile rFile : rFiles) { if (context.dataSourceIngestIsCancelled()) { @@ -287,6 +288,34 @@ final class ExtractRecycleBin extends Extract { return userNameMap; } + /** + * Get a list of files that start with $R and create a map of the file to + * their name. + * + * @param dataSource + * @return File map + * @throws TskCoreException + */ + private Map> makeRFileMap(Content dataSource) throws TskCoreException{ + FileManager fileManager = Case.getCurrentCase().getServices().getFileManager(); + List rFiles = fileManager.findFiles(dataSource, "$R%"); + Map> fileMap = new HashMap<>(); + + for (AbstractFile rFile: rFiles) { + String fileName = rFile.getName(); + List fileList = fileMap.get(fileName); + + if(fileList == null) { + fileList = new ArrayList<>(); + fileMap.put(fileName, fileList); + } + + fileList.add(rFile); + } + + return fileMap; + } + /** * Helper functions to get the user ID from the iFile parent path. User ids * will be of the form S-. From 0aeabbb0cd54c1c66c2c90d9fab0dcc1663bfba6 Mon Sep 17 00:00:00 2001 From: Kelly Kelly Date: Thu, 15 Aug 2019 10:30:39 -0400 Subject: [PATCH 06/24] Fixed codacy issues --- .../sleuthkit/autopsy/recentactivity/ExtractRecycleBin.java | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/ExtractRecycleBin.java b/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/ExtractRecycleBin.java index 08641a164e..cfa6aa997d 100755 --- a/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/ExtractRecycleBin.java +++ b/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/ExtractRecycleBin.java @@ -162,7 +162,6 @@ final class ExtractRecycleBin extends Extract { return; } - String rFileName = iFile.getName().replace("$I", "$R"); //NON-NLS String userID = getUserIDFromPath(iFile.getParentPath()); String userName = ""; if (!userID.isEmpty()) { @@ -174,6 +173,8 @@ final class ExtractRecycleBin extends Extract { } List rFiles; + + String rFileName = iFile.getName().replace("$I", "$R"); //NON-NLS try { rFiles = fileManager.findFiles(dataSource, rFileName, iFile.getParentPath()); @@ -296,7 +297,7 @@ final class ExtractRecycleBin extends Extract { * @return String user id */ private String getUserIDFromPath(String iFileParentPath) { - int index = iFileParentPath.indexOf("-") - 1; + int index = iFileParentPath.indexOf('-') - 1; if (index >= 0) { return (iFileParentPath.substring(index)).replace("/", ""); } else { From 91b08e400199211449e8758e246afbe80aac18fc Mon Sep 17 00:00:00 2001 From: Kelly Kelly Date: Thu, 22 Aug 2019 09:43:21 -0400 Subject: [PATCH 07/24] Inital pass of creating deleted files for recycle files. --- .../recentactivity/ExtractRecycleBin.java | 126 +++++++++++++++++- 1 file changed, 121 insertions(+), 5 deletions(-) diff --git a/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/ExtractRecycleBin.java b/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/ExtractRecycleBin.java index 926f8b2d9f..4c9f4b9618 100755 --- a/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/ExtractRecycleBin.java +++ b/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/ExtractRecycleBin.java @@ -28,6 +28,7 @@ import java.io.IOException; import java.nio.ByteBuffer; import java.nio.ByteOrder; import java.nio.file.Files; +import java.nio.file.Path; import java.nio.file.Paths; import java.util.ArrayList; import java.util.Arrays; @@ -35,6 +36,7 @@ import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.logging.Level; +import org.openide.util.Exceptions; import org.openide.util.NbBundle.Messages; import org.sleuthkit.autopsy.casemodule.Case; import org.sleuthkit.autopsy.casemodule.services.FileManager; @@ -51,7 +53,10 @@ import static org.sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE.TSK_PAT import static org.sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE.TSK_USER_ID; import static org.sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE.TSK_USER_NAME; import org.sleuthkit.datamodel.Content; +import org.sleuthkit.datamodel.FsContent; +import org.sleuthkit.datamodel.SleuthkitCase; import org.sleuthkit.datamodel.TskCoreException; +import org.sleuthkit.datamodel.TskData; import org.sleuthkit.datamodel.TskDataException; /** @@ -134,7 +139,7 @@ final class ExtractRecycleBin extends Extract { return; } - processIFiles(context, recycleBinArtifactType, iFile, userNameMap, rFileMap, tempRARecycleBinPath); + processIFiles(dataSource, context, recycleBinArtifactType, iFile, userNameMap, rFileMap, tempRARecycleBinPath); } (new File(tempRARecycleBinPath)).delete(); @@ -150,7 +155,7 @@ final class ExtractRecycleBin extends Extract { * @param userNameMap Map of user ids to names * @param tempRARecycleBinPath Temp directory path */ - private void processIFiles(IngestJobContext context, BlackboardArtifact.Type recycleBinArtifactType, AbstractFile iFile, Map userNameMap, Map> rFileMap, String tempRARecycleBinPath) { + private void processIFiles(Content dataSource, IngestJobContext context, BlackboardArtifact.Type recycleBinArtifactType, AbstractFile iFile, Map userNameMap, Map> rFileMap, String tempRARecycleBinPath) { String tempFilePath = tempRARecycleBinPath + File.separator + iFile.getName(); try { try { @@ -188,7 +193,7 @@ final class ExtractRecycleBin extends Extract { if(rFiles == null) { return; } - + SleuthkitCase skCase = Case.getCurrentCase().getSleuthkitCase(); for (AbstractFile rFile : rFiles) { if (context.dataSourceIngestIsCancelled()) { return; @@ -198,6 +203,16 @@ final class ExtractRecycleBin extends Extract { && iFile.getMetaFlagsAsString().equals(rFile.getMetaFlagsAsString())) { try { postArtifact(createArtifact(rFile, recycleBinArtifactType, metaData.getFileName(), userName, metaData.getDeletedTimeStamp())); + if(rFile instanceof FsContent) { + if(rFile.isDir()) { + AbstractFile directory = getOrMakeFolder(Case.getCurrentCase().getSleuthkitCase(), (FsContent)rFile, metaData.getFileName()); + popuplateDirectory(Case.getCurrentCase().getSleuthkitCase(), directory, rFile.getChildren(), metaData.getFileName(), metaData.getDeletedTimeStamp()); + + } else { + AbstractFile folder = getOrMakeFolder(Case.getCurrentCase().getSleuthkitCase(), (FsContent)rFile.getParent(), Paths.get(metaData.getFileName()).getParent().toString()); + addFileToDirectory(skCase, rFile, folder, Paths.get(metaData.getFileName()).getFileName().toString(), metaData.getDeletedTimeStamp()); + } + } } catch (TskCoreException ex) { logger.log(Level.WARNING, String.format("Unable to add attributes to artifact %s", rFile.getName()), ex); //NON-NLS } @@ -207,6 +222,34 @@ final class ExtractRecycleBin extends Extract { (new File(tempFilePath)).delete(); } } + + /** + * + * @param skCase + * @param folder + * @param children + * @param parentPath + * @param deletedTimeStamp + * @throws TskCoreException + */ + private void popuplateDirectory(SleuthkitCase skCase, AbstractFile folder, List recycledChildren, String parentPath, long deletedTimeStamp) throws TskCoreException { + if (recycledChildren == null) { + return; + } + + for(Content child: recycledChildren) { + if(child instanceof AbstractFile) { + AbstractFile fileChild = (AbstractFile) child; + if(fileChild.isFile()) { + addFileToDirectory(skCase, fileChild, folder, fileChild.getName(), deletedTimeStamp); + } else if(fileChild.isDir()) { + String newPath = parentPath + File.separator + fileChild.getName(); + AbstractFile childFolder = getOrMakeFolder(skCase, (FsContent)fileChild, parentPath); + popuplateDirectory(skCase, childFolder, fileChild.getChildren(), newPath, deletedTimeStamp); + } + } + } + } /** * Parse the $I file. @@ -383,7 +426,80 @@ final class ExtractRecycleBin extends Extract { return bba; } - + + private AbstractFile getOrMakeFolder(SleuthkitCase skCase, FsContent dataSource, String path) throws TskCoreException { + + String parentPath = getParentPath(path); + String folderName = getFileName(path); + + List files = null; + if(parentPath != null) { + if(!parentPath.equals("/")) { + parentPath = parentPath + "/"; + } + files = skCase.findAllFilesWhere(String.format("fs_obj_id=%s AND parent_path='%s' AND name='%s'", dataSource.getFileSystemId(), parentPath, folderName != null ? folderName : "")); + } else { + files = skCase.findAllFilesWhere(String.format("fs_obj_id=%s AND parent_path='/' AND name=''", dataSource.getFileSystemId())); + } + + if(files == null || files.isEmpty()) { + AbstractFile parent = getOrMakeFolder(skCase, dataSource, parentPath); + return skCase.addVirtualDirectory(parent.getId(), folderName); + + } else { + return files.get(0); + } + } + + private void addFileToDirectory (SleuthkitCase skCase, AbstractFile rFile, Content parentDir, String fileName, long deletedTime) throws TskCoreException { + FsContent fsContent = (FsContent)rFile; + + skCase.addFileSystemFile(fsContent.getFileSystemId(), + rFile.getDataSourceObjectId(), + rFile.getAttrType(), + rFile.getAttributeId(), + fileName, + TskData.TSK_FS_NAME_FLAG_ENUM.UNALLOC, + rFile.getSize(), + 0,0,0,deletedTime, + rFile.getMetaAddr(), + (int)rFile.getMetaSeq(), + true, parentDir); + } + + /** + * + * @param path + * @return + */ + String normalizeFilePath(String pathString) { + if (pathString == null || pathString.isEmpty()) { + return null; + } + + Path path = Paths.get(pathString); + Path rootPath = path.getRoot(); + + String rootless = pathString.replace(rootPath.toString().replace("\\", ""), ""); + return rootless.replace("\\", "/"); + } + + String getFileName(String filePath) { + Path fileNamePath = Paths.get(filePath).getFileName(); + if(fileNamePath != null) { + return fileNamePath.toString(); + } + return filePath; + } + + String getParentPath(String path) { + Path parentPath = Paths.get(path).getParent(); + if(parentPath != null) { + return normalizeFilePath(parentPath.toString()); + } + return null; + } + /** * Stores the data from the $I files. */ @@ -430,7 +546,7 @@ final class ExtractRecycleBin extends Extract { * @return String name of the deleted file */ String getFileName() { - return fileName; + return fileName.trim(); } } } From 41c71a0b03273ce9d34fea7680a8a291a831674b Mon Sep 17 00:00:00 2001 From: Kelly Kelly Date: Thu, 22 Aug 2019 12:02:26 -0400 Subject: [PATCH 08/24] updated after review comments --- .../recentactivity/ExtractRecycleBin.java | 329 ++++++++++-------- 1 file changed, 192 insertions(+), 137 deletions(-) diff --git a/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/ExtractRecycleBin.java b/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/ExtractRecycleBin.java index 4c9f4b9618..8beaa0bd87 100755 --- a/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/ExtractRecycleBin.java +++ b/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/ExtractRecycleBin.java @@ -36,7 +36,6 @@ import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.logging.Level; -import org.openide.util.Exceptions; import org.openide.util.NbBundle.Messages; import org.sleuthkit.autopsy.casemodule.Case; import org.sleuthkit.autopsy.casemodule.services.FileManager; @@ -87,7 +86,7 @@ final class ExtractRecycleBin extends Extract { // At this time it was decided that we would not include TSK_RECYCLE_BIN // in the default list of BlackboardArtifact types. try { - createRecycleBinArtifactType(); + createRecycleBinArtifactType(); } catch (TskCoreException ex) { logger.log(Level.WARNING, String.format("%s may not have been created.", RECYCLE_BIN_ARTIFACT_NAME), ex); } @@ -102,16 +101,16 @@ final class ExtractRecycleBin extends Extract { return; } Map userNameMap; - + try { userNameMap = makeUserNameMap(dataSource); } catch (TskCoreException ex) { - logger.log(Level.WARNING, "Unable to create OS Account user name map", ex); - // This is not the end of the world we will just continue without - // user names - userNameMap = new HashMap<>(); + logger.log(Level.WARNING, "Unable to create OS Account user name map", ex); + // This is not the end of the world we will just continue without + // user names + userNameMap = new HashMap<>(); } - + FileManager fileManager = Case.getCurrentCase().getServices().getFileManager(); Map> rFileMap; @@ -130,7 +129,7 @@ final class ExtractRecycleBin extends Extract { logger.log(Level.WARNING, "Unable to find recycle bin I files.", ex); //NON-NLS return; // No need to continue } - + String tempRARecycleBinPath = RAImageIngestModule.getRATempPath(Case.getCurrentCase(), "recyclebin"); //NON-NLS for (AbstractFile iFile : iFiles) { @@ -138,24 +137,23 @@ final class ExtractRecycleBin extends Extract { if (context.dataSourceIngestIsCancelled()) { return; } - - processIFiles(dataSource, context, recycleBinArtifactType, iFile, userNameMap, rFileMap, tempRARecycleBinPath); + + processIFile(context, recycleBinArtifactType, iFile, userNameMap, rFileMap, tempRARecycleBinPath); } (new File(tempRARecycleBinPath)).delete(); } - + /** * Process each individual iFile. - * - * @param dataSource + * * @param context * @param recycleBinArtifactType Module created artifact type - * @param iFile The AbstractFile to process - * @param userNameMap Map of user ids to names - * @param tempRARecycleBinPath Temp directory path + * @param iFile The AbstractFile to process + * @param userNameMap Map of user ids to names + * @param tempRARecycleBinPath Temp directory path */ - private void processIFiles(Content dataSource, IngestJobContext context, BlackboardArtifact.Type recycleBinArtifactType, AbstractFile iFile, Map userNameMap, Map> rFileMap, String tempRARecycleBinPath) { + private void processIFile(IngestJobContext context, BlackboardArtifact.Type recycleBinArtifactType, AbstractFile iFile, Map userNameMap, Map> rFileMap, String tempRARecycleBinPath) { String tempFilePath = tempRARecycleBinPath + File.separator + iFile.getName(); try { try { @@ -187,10 +185,10 @@ final class ExtractRecycleBin extends Extract { } String rFileName = iFile.getName().replace("$I", "$R"); //NON-NLS - + List rFiles = rFileMap.get(rFileName); - - if(rFiles == null) { + + if (rFiles == null) { return; } SleuthkitCase skCase = Case.getCurrentCase().getSleuthkitCase(); @@ -199,18 +197,18 @@ final class ExtractRecycleBin extends Extract { return; } - if (iFile.getParentPath().equals(rFile.getParentPath()) + if (iFile.getParentPath().equals(rFile.getParentPath()) && iFile.getMetaFlagsAsString().equals(rFile.getMetaFlagsAsString())) { try { postArtifact(createArtifact(rFile, recycleBinArtifactType, metaData.getFileName(), userName, metaData.getDeletedTimeStamp())); - if(rFile instanceof FsContent) { - if(rFile.isDir()) { - AbstractFile directory = getOrMakeFolder(Case.getCurrentCase().getSleuthkitCase(), (FsContent)rFile, metaData.getFileName()); - popuplateDirectory(Case.getCurrentCase().getSleuthkitCase(), directory, rFile.getChildren(), metaData.getFileName(), metaData.getDeletedTimeStamp()); - + if (rFile instanceof FsContent) { + if (rFile.isDir()) { + AbstractFile directory = getOrMakeFolder(Case.getCurrentCase().getSleuthkitCase(), (FsContent) rFile, metaData.getFileName()); + popuplateDeletedDirectory(Case.getCurrentCase().getSleuthkitCase(), directory, rFile.getChildren(), metaData.getFileName(), metaData.getDeletedTimeStamp()); + } else { - AbstractFile folder = getOrMakeFolder(Case.getCurrentCase().getSleuthkitCase(), (FsContent)rFile.getParent(), Paths.get(metaData.getFileName()).getParent().toString()); - addFileToDirectory(skCase, rFile, folder, Paths.get(metaData.getFileName()).getFileName().toString(), metaData.getDeletedTimeStamp()); + AbstractFile folder = getOrMakeFolder(Case.getCurrentCase().getSleuthkitCase(), (FsContent) rFile.getParent(), Paths.get(metaData.getFileName()).getParent().toString()); + addFileSystemFile(skCase, (FsContent)rFile, folder, Paths.get(metaData.getFileName()).getFileName().toString(), metaData.getDeletedTimeStamp()); } } } catch (TskCoreException ex) { @@ -222,30 +220,35 @@ final class ExtractRecycleBin extends Extract { (new File(tempFilePath)).delete(); } } - + /** - * - * @param skCase - * @param folder - * @param children - * @param parentPath - * @param deletedTimeStamp - * @throws TskCoreException + * Add the children of recycled $R folder to the folder. + * + * @param skCase The current Sleuthkit case + * @param parentFolder The folder to folder the deleted files are to be + * added. + * @param children The recycled children of the $R folder + * @param parentPath String path to the directory the children were + * deleted from + * @param deletedTimeStamp The time at which the files were deleted, + * inherited from the $R file. + * + * @throws TskCoreException */ - private void popuplateDirectory(SleuthkitCase skCase, AbstractFile folder, List recycledChildren, String parentPath, long deletedTimeStamp) throws TskCoreException { + private void popuplateDeletedDirectory(SleuthkitCase skCase, AbstractFile parentFolder, List recycledChildren, String parentPath, long deletedTimeStamp) throws TskCoreException { if (recycledChildren == null) { return; } - - for(Content child: recycledChildren) { - if(child instanceof AbstractFile) { - AbstractFile fileChild = (AbstractFile) child; - if(fileChild.isFile()) { - addFileToDirectory(skCase, fileChild, folder, fileChild.getName(), deletedTimeStamp); - } else if(fileChild.isDir()) { - String newPath = parentPath + File.separator + fileChild.getName(); - AbstractFile childFolder = getOrMakeFolder(skCase, (FsContent)fileChild, parentPath); - popuplateDirectory(skCase, childFolder, fileChild.getChildren(), newPath, deletedTimeStamp); + + for (Content child : recycledChildren) { + if (child instanceof FsContent) { + FsContent fsContent = (FsContent) child; + if (fsContent.isFile()) { + addFileSystemFile(skCase, fsContent, parentFolder, fsContent.getName(), deletedTimeStamp); + } else if (fsContent.isDir()) { + String newPath = parentPath + "\\" + fsContent.getName(); + AbstractFile childFolder = getOrMakeFolder(skCase, (FsContent) fsContent, parentPath); + popuplateDeletedDirectory(skCase, childFolder, fsContent.getChildren(), newPath, deletedTimeStamp); } } } @@ -290,7 +293,7 @@ final class ExtractRecycleBin extends Extract { long version = byteBuffer.getLong(); long fileSize = byteBuffer.getLong(); long timestamp = byteBuffer.getLong(); - + // Convert from windows FILETIME to Unix Epoch seconds timestamp = Util.filetimeToMillis(timestamp) / 1000; @@ -307,71 +310,73 @@ final class ExtractRecycleBin extends Extract { return new RecycledFileMetaData(fileSize, timestamp, fileName); } - + /** * Create a map of userids to usernames from the OS Accounts. - * + * * @param dataSource - * + * * @return A Map of userIDs and userNames - * - * @throws TskCoreException + * + * @throws TskCoreException */ - private Map makeUserNameMap(Content dataSource) throws TskCoreException{ + private Map makeUserNameMap(Content dataSource) throws TskCoreException { Map userNameMap = new HashMap<>(); - + List accounts = blackboard.getArtifacts(TSK_OS_ACCOUNT.getTypeID(), dataSource.getId()); - - for (BlackboardArtifact account: accounts) { + + for (BlackboardArtifact account : accounts) { BlackboardAttribute nameAttribute = getAttributeForArtifact(account, TSK_USER_NAME); BlackboardAttribute idAttribute = getAttributeForArtifact(account, TSK_USER_ID); - + String userName = nameAttribute != null ? nameAttribute.getDisplayString() : ""; String userID = idAttribute != null ? idAttribute.getDisplayString() : ""; - + if (!userID.isEmpty()) { userNameMap.put(userID, userName); } } - + return userNameMap; } - + /** - * Get a list of files that start with $R and create a map of the file to + * Get a list of files that start with $R and create a map of the file to * their name. - * + * * @param dataSource + * * @return File map - * @throws TskCoreException + * + * @throws TskCoreException */ - private Map> makeRFileMap(Content dataSource) throws TskCoreException{ + private Map> makeRFileMap(Content dataSource) throws TskCoreException { FileManager fileManager = Case.getCurrentCase().getServices().getFileManager(); List rFiles = fileManager.findFiles(dataSource, "$R%"); Map> fileMap = new HashMap<>(); - - for (AbstractFile rFile: rFiles) { + + for (AbstractFile rFile : rFiles) { String fileName = rFile.getName(); List fileList = fileMap.get(fileName); - - if(fileList == null) { + + if (fileList == null) { fileList = new ArrayList<>(); fileMap.put(fileName, fileList); } - + fileList.add(rFile); } - + return fileMap; } - + /** * Helper functions to get the user ID from the iFile parent path. User ids * will be of the form S-. - * + * * @param iFileParentPath String parent path of the iFile - * - * @return String user id + * + * @return String user id */ private String getUserIDFromPath(String iFileParentPath) { int index = iFileParentPath.indexOf('-') - 1; @@ -381,125 +386,175 @@ final class ExtractRecycleBin extends Extract { return ""; } } - + /** * Gets the attribute for the given type from the given artifact. - * + * * @param artifact BlackboardArtifact to get the attribute from - * @param type The BlackboardAttribute Type to get - * + * @param type The BlackboardAttribute Type to get + * * @return BlackboardAttribute for given artifact and type - * - * @throws TskCoreException + * + * @throws TskCoreException */ - private BlackboardAttribute getAttributeForArtifact(BlackboardArtifact artifact, BlackboardAttribute.ATTRIBUTE_TYPE type) throws TskCoreException{ - return artifact.getAttribute(new BlackboardAttribute.Type(BlackboardAttribute.ATTRIBUTE_TYPE.fromID(type.getTypeID()))); + private BlackboardAttribute getAttributeForArtifact(BlackboardArtifact artifact, BlackboardAttribute.ATTRIBUTE_TYPE type) throws TskCoreException { + return artifact.getAttribute(new BlackboardAttribute.Type(BlackboardAttribute.ATTRIBUTE_TYPE.fromID(type.getTypeID()))); } - + + /** + * Create TSK_RECYCLE_BIN artifact type. + * + * @throws TskCoreException + */ private void createRecycleBinArtifactType() throws TskCoreException { - try { + try { tskCase.addBlackboardArtifactType(RECYCLE_BIN_ARTIFACT_NAME, "Recycle Bin"); //NON-NLS } catch (TskDataException ex) { logger.log(Level.INFO, String.format("%s may have already been defined for this case", RECYCLE_BIN_ARTIFACT_NAME)); } } - + /** * Create the new artifact for the give rFile - * - * @param rFile AbstractFile to create the artifact for - * @param type Type of artifact to create + * + * @param rFile AbstractFile to create the artifact for + * @param type Type of artifact to create * @param fileName The original path of the deleted file * @param userName The name of the user that deleted the file * @param dateTime The time in epoch seconds that the file was deleted - * + * * @return Newly created artifact - * - * @throws TskCoreException + * + * @throws TskCoreException */ - private BlackboardArtifact createArtifact(AbstractFile rFile, BlackboardArtifact.Type type, String fileName, String userName, long dateTime) throws TskCoreException{ + private BlackboardArtifact createArtifact(AbstractFile rFile, BlackboardArtifact.Type type, String fileName, String userName, long dateTime) throws TskCoreException { BlackboardArtifact bba = rFile.newArtifact(type.getTypeID()); bba.addAttribute(new BlackboardAttribute(TSK_PATH, getName(), fileName)); bba.addAttribute(new BlackboardAttribute(TSK_DATETIME_DELETED, getName(), dateTime)); bba.addAttribute(new BlackboardAttribute(TSK_USER_NAME, getName(), userName == null || userName.isEmpty() ? "" : userName)); - + return bba; } - + + /** + * Returns a folder for the given path. If the path does not exist the + * the folder is created. + * + * @param skCase + * @param dataSource + * @param path + * + * @return AbstractFile for the given path. + * + * @throws TskCoreException + */ private AbstractFile getOrMakeFolder(SleuthkitCase skCase, FsContent dataSource, String path) throws TskCoreException { - + String parentPath = getParentPath(path); String folderName = getFileName(path); - + List files = null; - if(parentPath != null) { - if(!parentPath.equals("/")) { + if (parentPath != null) { + if (!parentPath.equals("/")) { parentPath = parentPath + "/"; } - files = skCase.findAllFilesWhere(String.format("fs_obj_id=%s AND parent_path='%s' AND name='%s'", dataSource.getFileSystemId(), parentPath, folderName != null ? folderName : "")); + + files = skCase.findAllFilesWhere(String.format("fs_obj_id=%s AND parent_path='%s' AND name='%s'", + dataSource.getFileSystemId(), SleuthkitCase.escapeSingleQuotes(parentPath), folderName != null ? SleuthkitCase.escapeSingleQuotes(folderName) : "")); } else { files = skCase.findAllFilesWhere(String.format("fs_obj_id=%s AND parent_path='/' AND name=''", dataSource.getFileSystemId())); } - - if(files == null || files.isEmpty()) { - AbstractFile parent = getOrMakeFolder(skCase, dataSource, parentPath); + + if (files == null || files.isEmpty()) { + AbstractFile parent = getOrMakeFolder(skCase, dataSource, parentPath); return skCase.addVirtualDirectory(parent.getId(), folderName); - } else { return files.get(0); } } - - private void addFileToDirectory (SleuthkitCase skCase, AbstractFile rFile, Content parentDir, String fileName, long deletedTime) throws TskCoreException { - FsContent fsContent = (FsContent)rFile; - - skCase.addFileSystemFile(fsContent.getFileSystemId(), - rFile.getDataSourceObjectId(), - rFile.getAttrType(), - rFile.getAttributeId(), - fileName, - TskData.TSK_FS_NAME_FLAG_ENUM.UNALLOC, - rFile.getSize(), - 0,0,0,deletedTime, - rFile.getMetaAddr(), - (int)rFile.getMetaSeq(), - true, parentDir); - } - + /** + * Adds a new file system file that is unallocated and maps to the original + * file in recycle bin directory. * - * @param path - * @return + * @param skCase The current case. + * @param recycleBinFile The file from the recycle bin. + * @param parentDir The directory that the recycled file was deleted. + * @param fileName The name of the file. + * @param deletedTime The time the file was deleted. + * + * @throws TskCoreException + */ + private void addFileSystemFile(SleuthkitCase skCase, FsContent recycleBinFile, Content parentDir, String fileName, long deletedTime) throws TskCoreException { + skCase.addFileSystemFile(recycleBinFile.getFileSystemId(), + recycleBinFile.getDataSourceObjectId(), + recycleBinFile.getAttrType(), + recycleBinFile.getAttributeId(), + fileName, + TskData.TSK_FS_NAME_FLAG_ENUM.UNALLOC, + recycleBinFile.getSize(), + 0, 0, 0, deletedTime, + recycleBinFile.getMetaAddr(), + (int) recycleBinFile.getMetaSeq(), + true, parentDir); + } + + /** + * Clean up the windows path string to match what the autopsy db uses. + * + * @param path The file\folder path to normalize + * + * @return New path string with the root removed (ie X:) and the slashes + * changed from windows to unix. */ String normalizeFilePath(String pathString) { if (pathString == null || pathString.isEmpty()) { return null; } - + Path path = Paths.get(pathString); - Path rootPath = path.getRoot(); - - String rootless = pathString.replace(rootPath.toString().replace("\\", ""), ""); - return rootless.replace("\\", "/"); + int nameCount = path.getNameCount(); + if(nameCount > 0) { + String rootless = "/" + path.subpath(0, nameCount); + return rootless.replace("\\", "/"); + } else { + return "/"; + } } - + + /** + * Helper function get from the given path either the file name or + * the last directory in the path. + * + * @param filePath The file\directory path + * + * @return If file path, returns the file name. If directory path the + * The last directory in the path is returned. + */ String getFileName(String filePath) { Path fileNamePath = Paths.get(filePath).getFileName(); - if(fileNamePath != null) { + if (fileNamePath != null) { return fileNamePath.toString(); } return filePath; } - + + /** + * Returns the parent path for the given path. + * + * @param path Path string + * + * @return The parent path for the given path. + */ String getParentPath(String path) { Path parentPath = Paths.get(path).getParent(); - if(parentPath != null) { + if (parentPath != null) { return normalizeFilePath(parentPath.toString()); } return null; } - + /** * Stores the data from the $I files. */ @@ -524,7 +579,7 @@ final class ExtractRecycleBin extends Extract { /** * Returns the size of the recycled file. - * + * * @return Size of deleted file */ long getFileSize() { @@ -533,7 +588,7 @@ final class ExtractRecycleBin extends Extract { /** * Returns the time the file was deleted. - * + * * @return deleted time in epoch seconds. */ long getDeletedTimeStamp() { @@ -542,7 +597,7 @@ final class ExtractRecycleBin extends Extract { /** * Returns the name of the deleted file. - * + * * @return String name of the deleted file */ String getFileName() { From 7d1c3b37e9676a3e4198e1af4254427d5d44c137 Mon Sep 17 00:00:00 2001 From: Kelly Kelly Date: Thu, 22 Aug 2019 14:13:36 -0400 Subject: [PATCH 09/24] modified the temp name to be unique --- .../sleuthkit/autopsy/recentactivity/ExtractRecycleBin.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/ExtractRecycleBin.java b/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/ExtractRecycleBin.java index 8beaa0bd87..9690a04aa0 100755 --- a/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/ExtractRecycleBin.java +++ b/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/ExtractRecycleBin.java @@ -36,6 +36,7 @@ import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.logging.Level; +import org.joda.time.Instant; import org.openide.util.NbBundle.Messages; import org.sleuthkit.autopsy.casemodule.Case; import org.sleuthkit.autopsy.casemodule.services.FileManager; @@ -154,7 +155,7 @@ final class ExtractRecycleBin extends Extract { * @param tempRARecycleBinPath Temp directory path */ private void processIFile(IngestJobContext context, BlackboardArtifact.Type recycleBinArtifactType, AbstractFile iFile, Map userNameMap, Map> rFileMap, String tempRARecycleBinPath) { - String tempFilePath = tempRARecycleBinPath + File.separator + iFile.getName(); + String tempFilePath = tempRARecycleBinPath + File.separator + Instant.now().toString() + iFile.getName(); try { try { ContentUtils.writeToFile(iFile, new File(tempFilePath)); From 6385c5e0705f63256d8b2c8501873e98a633d990 Mon Sep 17 00:00:00 2001 From: Brian Carrier Date: Thu, 22 Aug 2019 16:06:34 -0400 Subject: [PATCH 10/24] Added comments. No logic changes. --- .../recentactivity/ExtractRecycleBin.java | 22 ++++++++++++++----- 1 file changed, 16 insertions(+), 6 deletions(-) diff --git a/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/ExtractRecycleBin.java b/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/ExtractRecycleBin.java index 9690a04aa0..1086a346eb 100755 --- a/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/ExtractRecycleBin.java +++ b/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/ExtractRecycleBin.java @@ -101,8 +101,9 @@ final class ExtractRecycleBin extends Extract { // If this doesn't work bail. return; } + + // map SIDs to user names so that we can include that in the artifact Map userNameMap; - try { userNameMap = makeUserNameMap(dataSource); } catch (TskCoreException ex) { @@ -114,6 +115,7 @@ final class ExtractRecycleBin extends Extract { FileManager fileManager = Case.getCurrentCase().getServices().getFileManager(); + // Collect all of the $R files so that we can later easily map them to corresponding $I file Map> rFileMap; try { rFileMap = makeRFileMap(dataSource); @@ -122,8 +124,8 @@ final class ExtractRecycleBin extends Extract { return; // No $R files, no need to continue; } + // Get the $I files List iFiles; - try { iFiles = fileManager.findFiles(dataSource, "$I%"); //NON-NLS } catch (TskCoreException ex) { @@ -133,6 +135,7 @@ final class ExtractRecycleBin extends Extract { String tempRARecycleBinPath = RAImageIngestModule.getRATempPath(Case.getCurrentCase(), "recyclebin"); //NON-NLS + // cycle through the $I files and process each. for (AbstractFile iFile : iFiles) { if (context.dataSourceIngestIsCancelled()) { @@ -166,6 +169,7 @@ final class ExtractRecycleBin extends Extract { return; } + // get the original name, dates, etc. from the $I file RecycledFileMetaData metaData; try { metaData = parseIFile(tempFilePath); @@ -175,6 +179,7 @@ final class ExtractRecycleBin extends Extract { return; } + // each user has its own Recyle Bin folder. Figure out the user name based on its name . String userID = getUserIDFromPath(iFile.getParentPath()); String userName = ""; if (!userID.isEmpty()) { @@ -185,10 +190,9 @@ final class ExtractRecycleBin extends Extract { return; } + // get the corresponding $R file, which is in the same folder and has the file content String rFileName = iFile.getName().replace("$I", "$R"); //NON-NLS - List rFiles = rFileMap.get(rFileName); - if (rFiles == null) { return; } @@ -202,7 +206,13 @@ final class ExtractRecycleBin extends Extract { && iFile.getMetaFlagsAsString().equals(rFile.getMetaFlagsAsString())) { try { postArtifact(createArtifact(rFile, recycleBinArtifactType, metaData.getFileName(), userName, metaData.getDeletedTimeStamp())); + + // If we are processing a disk image, we will also make a deleted file entry so that the user + // sees the deleted file in its original folder. We re-use the metadata address so that the user + // can see the content. if (rFile instanceof FsContent) { + // if the user deleted a folder, then we need to recusively go into it. Note the contents of the $R folder + // do not have corresponding $I files anymore. Only the $R folder does. if (rFile.isDir()) { AbstractFile directory = getOrMakeFolder(Case.getCurrentCase().getSleuthkitCase(), (FsContent) rFile, metaData.getFileName()); popuplateDeletedDirectory(Case.getCurrentCase().getSleuthkitCase(), directory, rFile.getChildren(), metaData.getFileName(), metaData.getDeletedTimeStamp()); @@ -280,7 +290,7 @@ final class ExtractRecycleBin extends Extract { * For versions of Windows prior to 10, header = 0x01. Windows 10+ header == * 0x02 * - * @param iFilePath + * @param iFilePath Path to local copy of file in temp folder * * @throws FileNotFoundException * @throws IOException @@ -440,7 +450,7 @@ final class ExtractRecycleBin extends Extract { /** * Returns a folder for the given path. If the path does not exist the - * the folder is created. + * the folder is created. Recursively makes as many parent folders as needed. * * @param skCase * @param dataSource From 4b9c08f19fd959516f719a1ea4514253f461452f Mon Sep 17 00:00:00 2001 From: Kelly Kelly Date: Mon, 26 Aug 2019 11:52:23 -0400 Subject: [PATCH 11/24] Changed the order of the args for addFileSystemFile --- .../recentactivity/Bundle.properties-MERGED | 8 ++++- .../recentactivity/ExtractRecycleBin.java | 33 ++++++++++--------- 2 files changed, 25 insertions(+), 16 deletions(-) diff --git a/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/Bundle.properties-MERGED b/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/Bundle.properties-MERGED index 40771a0d41..a54c840799 100755 --- a/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/Bundle.properties-MERGED +++ b/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/Bundle.properties-MERGED @@ -2,9 +2,14 @@ cannotBuildXmlParser=Unable to build XML parser: cannotLoadSEUQA=Unable to load Search Engine URL Query Analyzer settings file, SEUQAMappings.xml: cannotParseXml=Unable to parse XML file: ChromeCacheExtractor.moduleName=ChromeCacheExtractor +# {0} - module name +# {1} - row number +# {2} - table length +# {3} - cache path ChromeCacheExtractor.progressMsg={0}: Extracting cache entry {1} of {2} entries from {3} DataSourceUsage_AndroidMedia=Android Media Card DataSourceUsage_FlashDrive=Flash Drive +# {0} - OS name DataSourceUsageAnalyzer.customVolume.label=OS Drive ({0}) DataSourceUsageAnalyzer.parentModuleName=Recent Activity Extract.indexError.message=Failed to index artifact for keyword search. @@ -60,7 +65,7 @@ ExtractZone_progress_Msg=Extracting :Zone.Identifer files ExtractZone_Restricted=Restricted Sites Zone ExtractZone_Trusted=Trusted Sites Zone OpenIDE-Module-Display-Category=Ingest Module -OpenIDE-Module-Long-Description=Recent Activity ingest module.\n\nThe module extracts useful information about the recent user activity on the disk image being ingested, such as:\n\n- Recently open documents,\n- Web activity (sites visited, stored cookies, book marked sites, search engine queries, file downloads),\n- Recently attached devices,\n- Installed programs.\n\nThe module currently supports Windows only disk images.\nThe plugin is also fully functional when deployed on Windows version of Autopsy. +OpenIDE-Module-Long-Description=Recent Activity ingest module.\n\n\The module extracts useful information about the recent user activity on the disk image being ingested, such as:\n\n- Recently open documents,\n- Web activity (sites visited, stored cookies, book marked sites, search engine queries, file downloads),\n- Recently attached devices,\n- Installed programs.\n\nThe module currently supports Windows only disk images.\nThe plugin is also fully functional when deployed on Windows version of Autopsy. OpenIDE-Module-Name=RecentActivity OpenIDE-Module-Short-Description=Recent Activity finder ingest module Chrome.moduleName=Chrome @@ -183,6 +188,7 @@ RecentDocumentsByLnk.parentModuleName.noSpace=RecentActivity RecentDocumentsByLnk.parentModuleName=Recent Activity RegRipperFullNotFound=Full version RegRipper executable not found. RegRipperNotFound=Autopsy RegRipper executable not found. +# {0} - file name SearchEngineURLQueryAnalyzer.init.exception.msg=Unable to find {0}. SearchEngineURLQueryAnalyzer.moduleName.text=Search Engine SearchEngineURLQueryAnalyzer.engineName.none=NONE diff --git a/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/ExtractRecycleBin.java b/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/ExtractRecycleBin.java index 1086a346eb..f461a2d026 100755 --- a/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/ExtractRecycleBin.java +++ b/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/ExtractRecycleBin.java @@ -158,7 +158,7 @@ final class ExtractRecycleBin extends Extract { * @param tempRARecycleBinPath Temp directory path */ private void processIFile(IngestJobContext context, BlackboardArtifact.Type recycleBinArtifactType, AbstractFile iFile, Map userNameMap, Map> rFileMap, String tempRARecycleBinPath) { - String tempFilePath = tempRARecycleBinPath + File.separator + Instant.now().toString() + iFile.getName(); + String tempFilePath = tempRARecycleBinPath + File.separator + Instant.now().getMillis() + iFile.getName(); try { try { ContentUtils.writeToFile(iFile, new File(tempFilePath)); @@ -205,8 +205,8 @@ final class ExtractRecycleBin extends Extract { if (iFile.getParentPath().equals(rFile.getParentPath()) && iFile.getMetaFlagsAsString().equals(rFile.getMetaFlagsAsString())) { try { - postArtifact(createArtifact(rFile, recycleBinArtifactType, metaData.getFileName(), userName, metaData.getDeletedTimeStamp())); - + postArtifact(createArtifact(rFile, recycleBinArtifactType, metaData.getFullWindowsPath(), userName, metaData.getDeletedTimeStamp())); + // If we are processing a disk image, we will also make a deleted file entry so that the user // sees the deleted file in its original folder. We re-use the metadata address so that the user // can see the content. @@ -214,12 +214,12 @@ final class ExtractRecycleBin extends Extract { // if the user deleted a folder, then we need to recusively go into it. Note the contents of the $R folder // do not have corresponding $I files anymore. Only the $R folder does. if (rFile.isDir()) { - AbstractFile directory = getOrMakeFolder(Case.getCurrentCase().getSleuthkitCase(), (FsContent) rFile, metaData.getFileName()); - popuplateDeletedDirectory(Case.getCurrentCase().getSleuthkitCase(), directory, rFile.getChildren(), metaData.getFileName(), metaData.getDeletedTimeStamp()); + AbstractFile directory = getOrMakeFolder(Case.getCurrentCase().getSleuthkitCase(), (FsContent) rFile, metaData.getFullWindowsPath()); + popuplateDeletedDirectory(Case.getCurrentCase().getSleuthkitCase(), directory, rFile.getChildren(), metaData.getFullWindowsPath(), metaData.getDeletedTimeStamp()); } else { - AbstractFile folder = getOrMakeFolder(Case.getCurrentCase().getSleuthkitCase(), (FsContent) rFile.getParent(), Paths.get(metaData.getFileName()).getParent().toString()); - addFileSystemFile(skCase, (FsContent)rFile, folder, Paths.get(metaData.getFileName()).getFileName().toString(), metaData.getDeletedTimeStamp()); + AbstractFile folder = getOrMakeFolder(Case.getCurrentCase().getSleuthkitCase(), (FsContent) rFile.getParent(), Paths.get(metaData.getFullWindowsPath()).getParent().toString()); + addFileSystemFile(skCase, (FsContent)rFile, folder, Paths.get(metaData.getFullWindowsPath()).getFileName().toString(), metaData.getDeletedTimeStamp()); } } } catch (TskCoreException ex) { @@ -498,16 +498,18 @@ final class ExtractRecycleBin extends Extract { * @throws TskCoreException */ private void addFileSystemFile(SleuthkitCase skCase, FsContent recycleBinFile, Content parentDir, String fileName, long deletedTime) throws TskCoreException { - skCase.addFileSystemFile(recycleBinFile.getFileSystemId(), + skCase.addFileSystemFile( recycleBinFile.getDataSourceObjectId(), - recycleBinFile.getAttrType(), - recycleBinFile.getAttributeId(), + recycleBinFile.getFileSystemId(), fileName, - TskData.TSK_FS_NAME_FLAG_ENUM.UNALLOC, - recycleBinFile.getSize(), - 0, 0, 0, deletedTime, recycleBinFile.getMetaAddr(), (int) recycleBinFile.getMetaSeq(), + recycleBinFile.getAttrType(), + recycleBinFile.getAttributeId(), + TskData.TSK_FS_NAME_FLAG_ENUM.UNALLOC, + (short) (TskData.TSK_FS_META_FLAG_ENUM.UNALLOC.getValue() | TskData.TSK_FS_META_FLAG_ENUM.USED.getValue()), + recycleBinFile.getSize(), + 0, 0, 0, deletedTime, true, parentDir); } @@ -607,11 +609,12 @@ final class ExtractRecycleBin extends Extract { } /** - * Returns the name of the deleted file. + * Returns the full path to the deleted file or folder. This path will + * include the drive letter, ie C:\ * * @return String name of the deleted file */ - String getFileName() { + String getFullWindowsPath() { return fileName.trim(); } } From ea60f0292c888968d74d14c5897585ce73e0df4a Mon Sep 17 00:00:00 2001 From: Kelly Kelly Date: Wed, 11 Sep 2019 16:20:45 -0400 Subject: [PATCH 12/24] added the creation and modifty time to the file system file --- .../sleuthkit/autopsy/recentactivity/ExtractRecycleBin.java | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/ExtractRecycleBin.java b/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/ExtractRecycleBin.java index f461a2d026..f1f46677de 100755 --- a/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/ExtractRecycleBin.java +++ b/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/ExtractRecycleBin.java @@ -48,7 +48,10 @@ import org.sleuthkit.datamodel.AbstractFile; import org.sleuthkit.datamodel.BlackboardArtifact; import static org.sleuthkit.datamodel.BlackboardArtifact.ARTIFACT_TYPE.TSK_OS_ACCOUNT; import org.sleuthkit.datamodel.BlackboardAttribute; +import static org.sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DATETIME_ACCESSED; +import static org.sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DATETIME_CREATED; import static org.sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DATETIME_DELETED; +import static org.sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DATETIME_MODIFIED; import static org.sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE.TSK_PATH; import static org.sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE.TSK_USER_ID; import static org.sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE.TSK_USER_NAME; @@ -444,7 +447,6 @@ final class ExtractRecycleBin extends Extract { bba.addAttribute(new BlackboardAttribute(TSK_PATH, getName(), fileName)); bba.addAttribute(new BlackboardAttribute(TSK_DATETIME_DELETED, getName(), dateTime)); bba.addAttribute(new BlackboardAttribute(TSK_USER_NAME, getName(), userName == null || userName.isEmpty() ? "" : userName)); - return bba; } @@ -509,7 +511,7 @@ final class ExtractRecycleBin extends Extract { TskData.TSK_FS_NAME_FLAG_ENUM.UNALLOC, (short) (TskData.TSK_FS_META_FLAG_ENUM.UNALLOC.getValue() | TskData.TSK_FS_META_FLAG_ENUM.USED.getValue()), recycleBinFile.getSize(), - 0, 0, 0, deletedTime, + recycleBinFile.getCtime(), recycleBinFile.getCrtime(), recycleBinFile.getAtime(), deletedTime, true, parentDir); } From 0e9359aae672ef93d4abf84a610f2c08ab80a302 Mon Sep 17 00:00:00 2001 From: esaunders Date: Wed, 11 Sep 2019 16:33:52 -0400 Subject: [PATCH 13/24] Added instructions for downloading and installing OpenJDK and OpenJFX. --- Running_Linux_OSX.txt | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/Running_Linux_OSX.txt b/Running_Linux_OSX.txt index 1edf48eb13..7244c6320d 100644 --- a/Running_Linux_OSX.txt +++ b/Running_Linux_OSX.txt @@ -9,10 +9,19 @@ The following need to be done at least once. They do not need to be repeated for -- Linux: % sudo apt-get install testdisk -- OS X: % brew install testdisk -- Install Oracle Java and set JAVA_HOME. --- Linux: Use the instructions here: https://medium.com/coderscorner/installing-oracle-java-8-in-ubuntu-16-10-845507b13343 - NOTE: You may need to log out and back in again after setting JAVA_HOME before the Autopsy +- Install a Java 8 JRE and JavaFX 8 and set JAVA_HOME. +-- Linux: Any Java 8 version of OpenJDK/OpenJFX distribution should suffice. The following instructions use the Zulu Community distribution. + 1. Download a 64 bit Java 8 JRE for your specific platform from https://www.azul.com/downloads/zulu-community + 2. Install the JRE. e.g. 'sudo apt install ./zulu8.40.0.25-ca-jre8.0.222-linux_amd64.deb' + 3. Download a 64 bit Java 8 JavaFX for your specific platform from the same location. + 4. Extract the contents of the JavaFX archive into the folder where the JRE was installed. + e.g. 'cd /usr/lib/jvm/zre-8-amd64; sudo tar xzf ~/Downloads/zulu8.40.0.25-ca-fx-jre8.0.222-linux_x64.tar.gz --strip-components=1' + 5. Confirm Java 8 is being found by running 'java -version' + 6. Set JAVA_HOME environment variable to location of JRE installation (e.g. /usr/lib/jvm/zre-8-amd64) + + NOTE: You may need to log out and back in again after setting JAVA_HOME before the Autopsy unix_setup.sh script can see the value. + -- OS X: Use The Oracle website: https://www.java.com/ Set JAVA_HOME with something like: export JAVA_HOME=`/usr/libexec/java_home` in .bash_profile From ef0446708d139310d5487fd87f6a2655aacdd02b Mon Sep 17 00:00:00 2001 From: Kelly Kelly Date: Thu, 12 Sep 2019 09:44:38 -0400 Subject: [PATCH 14/24] cleaned up imports --- .../sleuthkit/autopsy/recentactivity/ExtractRecycleBin.java | 3 --- 1 file changed, 3 deletions(-) diff --git a/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/ExtractRecycleBin.java b/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/ExtractRecycleBin.java index f1f46677de..3fa746cf82 100755 --- a/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/ExtractRecycleBin.java +++ b/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/ExtractRecycleBin.java @@ -48,10 +48,7 @@ import org.sleuthkit.datamodel.AbstractFile; import org.sleuthkit.datamodel.BlackboardArtifact; import static org.sleuthkit.datamodel.BlackboardArtifact.ARTIFACT_TYPE.TSK_OS_ACCOUNT; import org.sleuthkit.datamodel.BlackboardAttribute; -import static org.sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DATETIME_ACCESSED; -import static org.sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DATETIME_CREATED; import static org.sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DATETIME_DELETED; -import static org.sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DATETIME_MODIFIED; import static org.sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE.TSK_PATH; import static org.sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE.TSK_USER_ID; import static org.sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE.TSK_USER_NAME; From bbaa32957d2376f33fae8da395d93cb536edb1ae Mon Sep 17 00:00:00 2001 From: Kelly Kelly Date: Mon, 16 Sep 2019 11:24:03 -0400 Subject: [PATCH 15/24] Made the tag and hash hit filters generic --- .../autopsy/timeline/FilteredEventsModel.java | 44 ----------- .../timeline/ui/detailview/EventNodeBase.java | 54 +++++++------ .../filtering/datamodel/RootFilterState.java | 42 +++++----- .../filtering/datamodel/SqlFilterState.java | 9 +++ .../filtering/datamodel/TagsFilterState.java | 78 ------------------- 5 files changed, 56 insertions(+), 171 deletions(-) delete mode 100755 Core/src/org/sleuthkit/autopsy/timeline/ui/filtering/datamodel/TagsFilterState.java diff --git a/Core/src/org/sleuthkit/autopsy/timeline/FilteredEventsModel.java b/Core/src/org/sleuthkit/autopsy/timeline/FilteredEventsModel.java index 457939f04c..c49c85049d 100755 --- a/Core/src/org/sleuthkit/autopsy/timeline/FilteredEventsModel.java +++ b/Core/src/org/sleuthkit/autopsy/timeline/FilteredEventsModel.java @@ -35,9 +35,7 @@ import javafx.beans.InvalidationListener; import javafx.beans.property.ReadOnlyObjectProperty; import javafx.beans.property.ReadOnlyObjectWrapper; import javafx.collections.FXCollections; -import javafx.collections.ObservableList; import javafx.collections.ObservableMap; -import javafx.collections.ObservableSet; import static org.apache.commons.collections4.CollectionUtils.emptyIfNull; import static org.apache.commons.collections4.CollectionUtils.isNotEmpty; import org.joda.time.DateTimeZone; @@ -58,7 +56,6 @@ import org.sleuthkit.autopsy.timeline.events.TagsAddedEvent; import org.sleuthkit.autopsy.timeline.events.TagsDeletedEvent; import org.sleuthkit.autopsy.timeline.ui.filtering.datamodel.FilterState; import org.sleuthkit.autopsy.timeline.ui.filtering.datamodel.RootFilterState; -import org.sleuthkit.autopsy.timeline.ui.filtering.datamodel.TagsFilterState; import org.sleuthkit.autopsy.timeline.utils.CacheLoaderImpl; import org.sleuthkit.autopsy.timeline.utils.FilterUtils; import org.sleuthkit.autopsy.timeline.zooming.ZoomState; @@ -70,7 +67,6 @@ import org.sleuthkit.datamodel.ContentTag; import org.sleuthkit.datamodel.DataSource; import org.sleuthkit.datamodel.SleuthkitCase; import org.sleuthkit.datamodel.Tag; -import org.sleuthkit.datamodel.TagName; import org.sleuthkit.datamodel.TimelineManager; import org.sleuthkit.datamodel.TskCoreException; import org.sleuthkit.datamodel.TimelineEvent; @@ -81,10 +77,8 @@ import org.sleuthkit.datamodel.TimelineFilter.DataSourcesFilter; import org.sleuthkit.datamodel.TimelineFilter.EventTypeFilter; import org.sleuthkit.datamodel.TimelineFilter.FileTypesFilter; import org.sleuthkit.datamodel.TimelineFilter.HashHitsFilter; -import org.sleuthkit.datamodel.TimelineFilter.HashSetFilter; import org.sleuthkit.datamodel.TimelineFilter.HideKnownFilter; import org.sleuthkit.datamodel.TimelineFilter.RootFilter; -import org.sleuthkit.datamodel.TimelineFilter.TagNameFilter; import org.sleuthkit.datamodel.TimelineFilter.TagsFilter; import org.sleuthkit.datamodel.TimelineFilter.TextFilter; @@ -129,8 +123,6 @@ public final class FilteredEventsModel { private final LoadingCache> eventCountsCache; /** Map from datasource id to datasource name. */ private final ObservableMap datasourcesMap = FXCollections.observableHashMap(); - private final ObservableSet< String> hashSets = FXCollections.observableSet(); - private final ObservableList tagNames = FXCollections.observableArrayList(); // end caches /** @@ -171,8 +163,6 @@ public final class FilteredEventsModel { }; datasourcesMap.addListener(filterSyncListener); - hashSets.addListener(filterSyncListener); - tagNames.addListener(filterSyncListener); requestedFilter.set(getDefaultFilter()); @@ -248,15 +238,11 @@ public final class FilteredEventsModel { */ synchronized private void populateFilterData() throws TskCoreException { SleuthkitCase skCase = autoCase.getSleuthkitCase(); - hashSets.addAll(eventManager.getHashSetNames()); //because there is no way to remove a datasource we only add to this map. for (DataSource ds : skCase.getDataSources()) { datasourcesMap.putIfAbsent(ds.getId(), ds.getName()); } - - //should this only be tags applied to files or event bearing artifacts? - tagNames.setAll(skCase.getTagNamesInUse()); } /** @@ -269,22 +255,8 @@ public final class FilteredEventsModel { * with the tags in use in the case */ public void syncFilters(RootFilterState rootFilterState) { - TagsFilterState tagsFilterState = rootFilterState.getTagsFilterState(); - for (TagName tagName : tagNames) { - tagsFilterState.getFilter().addSubFilter(new TagNameFilter(tagName)); - } - for (FilterState tagFilterState : rootFilterState.getTagsFilterState().getSubFilterStates()) { - // disable states for tag names that don't exist in case. - tagFilterState.setDisabled(tagNames.contains(tagFilterState.getFilter().getTagName()) == false); - } - DataSourcesFilter dataSourcesFilter = rootFilterState.getDataSourcesFilterState().getFilter(); datasourcesMap.entrySet().forEach(entry -> dataSourcesFilter.addSubFilter(newDataSourceFromMapEntry(entry))); - - HashHitsFilter hashSetsFilter = rootFilterState.getHashHitsFilterState().getFilter(); - for (String hashSet : hashSets) { - hashSetsFilter.addSubFilter(new HashSetFilter(hashSet)); - } } /** @@ -351,10 +323,8 @@ public final class FilteredEventsModel { -> dataSourcesFilter.addSubFilter(newDataSourceFromMapEntry(dataSourceEntry))); HashHitsFilter hashHitsFilter = new HashHitsFilter(); - hashSets.stream().map(HashSetFilter::new).forEach(hashHitsFilter::addSubFilter); TagsFilter tagsFilter = new TagsFilter(); - tagNames.stream().map(TagNameFilter::new).forEach(tagsFilter::addSubFilter); FileTypesFilter fileTypesFilter = FilterUtils.createDefaultFileTypesFilter(); @@ -388,20 +358,6 @@ public final class FilteredEventsModel { return events; } - /** - * get a count of tagnames applied to the given event ids as a map from - * tagname displayname to count of tag applications - * - * @param eventIDsWithTags the event ids to get the tag counts map for - * - * @return a map from tagname displayname to count of applications - * - * @throws org.sleuthkit.datamodel.TskCoreException - */ - public Map getTagCountsByTagName(Set eventIDsWithTags) throws TskCoreException { - return eventManager.getTagCountsByTagName(eventIDsWithTags); - } - public List getEventIDs(Interval timeRange, FilterState filter) throws TskCoreException { final Interval overlap; diff --git a/Core/src/org/sleuthkit/autopsy/timeline/ui/detailview/EventNodeBase.java b/Core/src/org/sleuthkit/autopsy/timeline/ui/detailview/EventNodeBase.java index 17c6e3c394..1977d3ce6d 100755 --- a/Core/src/org/sleuthkit/autopsy/timeline/ui/detailview/EventNodeBase.java +++ b/Core/src/org/sleuthkit/autopsy/timeline/ui/detailview/EventNodeBase.java @@ -269,7 +269,7 @@ public abstract class EventNodeBase extends StackP } /** - * defer tooltip content creation till needed, this had a surprisingly large + * defer tooltip content creation until needed, this had a surprisingly large * impact on speed of loading the chart */ @NbBundle.Messages({"# {0} - counts", @@ -293,37 +293,35 @@ public abstract class EventNodeBase extends StackP @Override protected String call() throws Exception { - HashMap hashSetCounts = new HashMap<>(); - if (tlEvent.getEventIDsWithHashHits().isEmpty() == false) { - try { - //TODO:push this to DB - for (TimelineEvent tle : eventsModel.getEventsById(tlEvent.getEventIDsWithHashHits())) { - Set hashSetNames = sleuthkitCase.getContentById(tle.getFileObjID()).getHashSetNames(); - for (String hashSetName : hashSetNames) { - hashSetCounts.merge(hashSetName, 1L, Long::sum); - } - } - } catch (TskCoreException ex) { - LOGGER.log(Level.SEVERE, "Error getting hashset hit info for event.", ex); //NON-NLS - } - } - String hashSetCountsString = hashSetCounts.entrySet().stream() - .map((Map.Entry t) -> t.getKey() + " : " + t.getValue()) - .collect(Collectors.joining("\n")); +// HashMap hashSetCounts = new HashMap<>(); +// if (tlEvent.getEventIDsWithHashHits().isEmpty() == false) { +// try { +// //TODO:push this to DB +// for (TimelineEvent tle : eventsModel.getEventsById(tlEvent.getEventIDsWithHashHits())) { +// Set hashSetNames = sleuthkitCase.getContentById(tle.getFileObjID()).getHashSetNames(); +// for (String hashSetName : hashSetNames) { +// hashSetCounts.merge(hashSetName, 1L, Long::sum); +// } +// } +// } catch (TskCoreException ex) { +// LOGGER.log(Level.SEVERE, "Error getting hashset hit info for event.", ex); //NON-NLS +// } +// } +// String hashSetCountsString = hashSetCounts.entrySet().stream() +// .map((Map.Entry t) -> t.getKey() + " : " + t.getValue()) +// .collect(Collectors.joining("\n")); - Map tagCounts = new HashMap<>(); - if (tlEvent.getEventIDsWithTags().isEmpty() == false) { - tagCounts.putAll(eventsModel.getTagCountsByTagName(tlEvent.getEventIDsWithTags())); - } - String tagCountsString = tagCounts.entrySet().stream() - .map((Map.Entry t) -> t.getKey() + " : " + t.getValue()) - .collect(Collectors.joining("\n")); +// Map tagCounts = new HashMap<>(); +// if (tlEvent.getEventIDsWithTags().isEmpty() == false) { +// tagCounts.putAll(eventsModel.getTagCountsByTagName(tlEvent.getEventIDsWithTags())); +// } +// String tagCountsString = tagCounts.entrySet().stream() +// .map((Map.Entry t) -> t.getKey() + " : " + t.getValue()) +// .collect(Collectors.joining("\n")); return Bundle.EventNodeBase_tooltip_text(getEventIDs().size(), getEventType(), getDescription(), TimeLineController.getZonedFormatter().print(getStartMillis()), - TimeLineController.getZonedFormatter().print(getEndMillis() + 1000)) - + (hashSetCountsString.isEmpty() ? "" : Bundle.EventNodeBase_toolTip_hashSetHits(hashSetCountsString)) - + (tagCountsString.isEmpty() ? "" : Bundle.EventNodeBase_toolTip_tags(tagCountsString)); + TimeLineController.getZonedFormatter().print(getEndMillis() + 1000)); } @Override diff --git a/Core/src/org/sleuthkit/autopsy/timeline/ui/filtering/datamodel/RootFilterState.java b/Core/src/org/sleuthkit/autopsy/timeline/ui/filtering/datamodel/RootFilterState.java index 66f53c8998..d33a32ed21 100755 --- a/Core/src/org/sleuthkit/autopsy/timeline/ui/filtering/datamodel/RootFilterState.java +++ b/Core/src/org/sleuthkit/autopsy/timeline/ui/filtering/datamodel/RootFilterState.java @@ -35,21 +35,21 @@ import org.sleuthkit.datamodel.TimelineFilter.EventTypeFilter; import org.sleuthkit.datamodel.TimelineFilter.FileTypeFilter; import org.sleuthkit.datamodel.TimelineFilter.FileTypesFilter; import org.sleuthkit.datamodel.TimelineFilter.HashHitsFilter; -import org.sleuthkit.datamodel.TimelineFilter.HashSetFilter; import org.sleuthkit.datamodel.TimelineFilter.HideKnownFilter; import org.sleuthkit.datamodel.TimelineFilter.RootFilter; import org.sleuthkit.datamodel.TimelineFilter.TextFilter; +import org.sleuthkit.datamodel.TimelineFilter.TagsFilter; /** A FilterState for RootFilters. Provides named access to the sub - * filterstates. + * filter states. */ public class RootFilterState extends CompoundFilterState { private final CompoundFilterState eventTypeFilterState; private final SqlFilterState knownFilterState; private final SqlFilterState textFilterState; - private final TagsFilterState tagsFilterState; - private final CompoundFilterState hashHitsFilterState; + private final SqlFilterState tagsFilterState; + private final SqlFilterState hashHitsFilterState; private final CompoundFilterState dataSourcesFilterState; private final CompoundFilterState fileTypesFilterState; @@ -63,8 +63,8 @@ public class RootFilterState extends CompoundFilterState(delegate.getEventTypeFilter()), new SqlFilterState<>(delegate.getKnownFilter()), new SqlFilterState<>(delegate.getTextFilter()), - new TagsFilterState(delegate.getTagsFilter()), - new CompoundFilterState<>(delegate.getHashHitsFilter()), + new SqlFilterState<>(delegate.getTagsFilter()), + new SqlFilterState<>(delegate.getHashHitsFilter()), new CompoundFilterState<>(delegate.getDataSourcesFilter()), new CompoundFilterState<>(delegate.getFileTypesFilter()) ); @@ -74,8 +74,8 @@ public class RootFilterState extends CompoundFilterState eventTypeFilterState, SqlFilterState knownFilterState, SqlFilterState textFilterState, - TagsFilterState tagsFilterState, - CompoundFilterState hashHitsFilterState, + SqlFilterState tagsFilterState, + SqlFilterState hashHitsFilterState, CompoundFilterState dataSourcesFilterState, CompoundFilterState fileTypesFilterState) { super(filter, Arrays.asList(eventTypeFilterState, knownFilterState, textFilterState, tagsFilterState, hashHitsFilterState, dataSourcesFilterState, fileTypesFilterState)); @@ -133,11 +133,11 @@ public class RootFilterState extends CompoundFilterState getTagsFilterState() { return tagsFilterState; } - public CompoundFilterState getHashHitsFilterState() { + public SqlFilterState getHashHitsFilterState() { return hashHitsFilterState; } @@ -161,17 +161,17 @@ public class RootFilterState extends CompoundFilterState> getSubFilterStates() { diff --git a/Core/src/org/sleuthkit/autopsy/timeline/ui/filtering/datamodel/SqlFilterState.java b/Core/src/org/sleuthkit/autopsy/timeline/ui/filtering/datamodel/SqlFilterState.java index 5180dd3425..2f33ebec61 100755 --- a/Core/src/org/sleuthkit/autopsy/timeline/ui/filtering/datamodel/SqlFilterState.java +++ b/Core/src/org/sleuthkit/autopsy/timeline/ui/filtering/datamodel/SqlFilterState.java @@ -36,6 +36,15 @@ public class SqlFilterState extends AbstractF // the "Hide Known Filters", "Tags", "Hashsets" and "Text". // There are better ways to do this, but this works in a pinch this(filter, !(filter instanceof TimelineFilter.HideKnownFilter || filter instanceof TimelineFilter.TagsFilter || filter instanceof TimelineFilter.HashHitsFilter || filter instanceof TimelineFilter.TextFilter)); + + selectedProperty().addListener(selectedProperty -> { + if (filter instanceof TimelineFilter.TagsFilter) { + ((TimelineFilter.TagsFilter)filter).setTagged(isSelected()); + } else if (filter instanceof TimelineFilter.HashHitsFilter) { + ((TimelineFilter.HashHitsFilter)filter).setTagged(isSelected()); + } + }); + } /** diff --git a/Core/src/org/sleuthkit/autopsy/timeline/ui/filtering/datamodel/TagsFilterState.java b/Core/src/org/sleuthkit/autopsy/timeline/ui/filtering/datamodel/TagsFilterState.java deleted file mode 100755 index 12b17ed201..0000000000 --- a/Core/src/org/sleuthkit/autopsy/timeline/ui/filtering/datamodel/TagsFilterState.java +++ /dev/null @@ -1,78 +0,0 @@ -/* - * Autopsy Forensic Browser - * - * Copyright 2018-2019 Basis Technology Corp. - * Contact: carrier sleuthkit 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.timeline.ui.filtering.datamodel; - -import com.google.common.collect.Lists; -import java.util.Collection; -import javafx.collections.ListChangeListener; -import org.sleuthkit.datamodel.TimelineFilter.TagNameFilter; -import org.sleuthkit.datamodel.TimelineFilter.TagsFilter; - -/** - * Specialization of CompoundFilterState for TagName/Tags-Filter. - * - * Newly added subfilters made to be SELECTED when they are added. - */ -public class TagsFilterState extends CompoundFilterState { - - public TagsFilterState(TagsFilter delegate) { - super(delegate); - installSelectNewFiltersListener(); - - } - - public TagsFilterState(TagsFilter delegate, Collection> subFilterStates) { - super(delegate, subFilterStates); - installSelectNewFiltersListener(); - } - - private void installSelectNewFiltersListener() { - getSubFilterStates().addListener((ListChangeListener.Change> change) -> { - while (change.next()) { - change.getAddedSubList().forEach(filterState -> filterState.setSelected(true)); - } - }); - } - - @Override - public TagsFilterState copyOf() { - TagsFilterState copy = new TagsFilterState(getFilter().copyOf(), - Lists.transform(getSubFilterStates(), FilterState::copyOf)); - - copy.setSelected(isSelected()); - copy.setDisabled(isDisabled()); - return copy; - } - - @Override - public TagsFilter getActiveFilter() { - if (isActive() == false) { - return null; - } - - TagsFilter copy = new TagsFilter(); - //add active subfilters to copy. - getSubFilterStates().stream() - .filter(FilterState::isActive) - .map(FilterState::getActiveFilter) - .forEach(copy::addSubFilter); - - return copy; - } -} From e0066ebdca6831cb799a9e981c48abe7c9e91231 Mon Sep 17 00:00:00 2001 From: esaunders Date: Mon, 16 Sep 2019 16:07:25 -0400 Subject: [PATCH 16/24] Correctly set page number in the case where the user enters an invalid page number in the Go to Page field. --- .../autopsy/corecomponents/DataResultViewerTable.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/Core/src/org/sleuthkit/autopsy/corecomponents/DataResultViewerTable.java b/Core/src/org/sleuthkit/autopsy/corecomponents/DataResultViewerTable.java index 71f801282b..c79c8e613c 100644 --- a/Core/src/org/sleuthkit/autopsy/corecomponents/DataResultViewerTable.java +++ b/Core/src/org/sleuthkit/autopsy/corecomponents/DataResultViewerTable.java @@ -892,6 +892,8 @@ public class DataResultViewerTable extends AbstractDataResultViewer { "DataResultViewerTable.goToPageTextField.msgDlg=Please enter a valid page number between 1 and {0}", "DataResultViewerTable.goToPageTextField.err=Invalid page number"}) void gotoPage() { + int originalPage = currentPage; + try { currentPage = Integer.decode(gotoPageTextField.getText()); } catch (NumberFormatException e) { @@ -900,7 +902,7 @@ public class DataResultViewerTable extends AbstractDataResultViewer { } if (currentPage > totalPages || currentPage < 1) { - currentPage = 1; + currentPage = originalPage; JOptionPane.showMessageDialog(DataResultViewerTable.this, Bundle.DataResultViewerTable_goToPageTextField_msgDlg(totalPages), Bundle.DataResultViewerTable_goToPageTextField_err(), From 3f8d5727c9dfaaee940c69061396a5f19c6c9dba Mon Sep 17 00:00:00 2001 From: Kelly Kelly Date: Tue, 17 Sep 2019 14:56:08 -0400 Subject: [PATCH 17/24] Removed call to super.createSheet. --- .../autopsy/communications/relationships/ContactNode.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Core/src/org/sleuthkit/autopsy/communications/relationships/ContactNode.java b/Core/src/org/sleuthkit/autopsy/communications/relationships/ContactNode.java index 33b9d16724..462bb6f8fa 100755 --- a/Core/src/org/sleuthkit/autopsy/communications/relationships/ContactNode.java +++ b/Core/src/org/sleuthkit/autopsy/communications/relationships/ContactNode.java @@ -70,7 +70,7 @@ final class ContactNode extends BlackboardArtifactNode { @Override protected Sheet createSheet() { - Sheet sheet = super.createSheet(); + Sheet sheet = new Sheet(); final BlackboardArtifact artifact = getArtifact(); BlackboardArtifact.ARTIFACT_TYPE fromID = BlackboardArtifact.ARTIFACT_TYPE.fromID(artifact.getArtifactTypeID()); From 7d2aedcf95f390bf41d22597e382c4ce60718d30 Mon Sep 17 00:00:00 2001 From: Kelly Kelly Date: Tue, 17 Sep 2019 15:13:40 -0400 Subject: [PATCH 18/24] removed commented out code --- .../timeline/ui/detailview/EventNodeBase.java | 26 ------------------- 1 file changed, 26 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/timeline/ui/detailview/EventNodeBase.java b/Core/src/org/sleuthkit/autopsy/timeline/ui/detailview/EventNodeBase.java index 1977d3ce6d..19aada1393 100755 --- a/Core/src/org/sleuthkit/autopsy/timeline/ui/detailview/EventNodeBase.java +++ b/Core/src/org/sleuthkit/autopsy/timeline/ui/detailview/EventNodeBase.java @@ -293,32 +293,6 @@ public abstract class EventNodeBase extends StackP @Override protected String call() throws Exception { -// HashMap hashSetCounts = new HashMap<>(); -// if (tlEvent.getEventIDsWithHashHits().isEmpty() == false) { -// try { -// //TODO:push this to DB -// for (TimelineEvent tle : eventsModel.getEventsById(tlEvent.getEventIDsWithHashHits())) { -// Set hashSetNames = sleuthkitCase.getContentById(tle.getFileObjID()).getHashSetNames(); -// for (String hashSetName : hashSetNames) { -// hashSetCounts.merge(hashSetName, 1L, Long::sum); -// } -// } -// } catch (TskCoreException ex) { -// LOGGER.log(Level.SEVERE, "Error getting hashset hit info for event.", ex); //NON-NLS -// } -// } -// String hashSetCountsString = hashSetCounts.entrySet().stream() -// .map((Map.Entry t) -> t.getKey() + " : " + t.getValue()) -// .collect(Collectors.joining("\n")); - -// Map tagCounts = new HashMap<>(); -// if (tlEvent.getEventIDsWithTags().isEmpty() == false) { -// tagCounts.putAll(eventsModel.getTagCountsByTagName(tlEvent.getEventIDsWithTags())); -// } -// String tagCountsString = tagCounts.entrySet().stream() -// .map((Map.Entry t) -> t.getKey() + " : " + t.getValue()) -// .collect(Collectors.joining("\n")); - return Bundle.EventNodeBase_tooltip_text(getEventIDs().size(), getEventType(), getDescription(), TimeLineController.getZonedFormatter().print(getStartMillis()), TimeLineController.getZonedFormatter().print(getEndMillis() + 1000)); From f542ca7520f9faf71cec235530668d87549f224f Mon Sep 17 00:00:00 2001 From: Kelly Kelly Date: Tue, 17 Sep 2019 15:29:29 -0400 Subject: [PATCH 19/24] Updates based on review comment --- .../timeline/ui/detailview/EventNodeBase.java | 5 ----- .../ui/filtering/datamodel/RootFilterState.java | 12 ------------ 2 files changed, 17 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/timeline/ui/detailview/EventNodeBase.java b/Core/src/org/sleuthkit/autopsy/timeline/ui/detailview/EventNodeBase.java index 19aada1393..3ee088f2ad 100755 --- a/Core/src/org/sleuthkit/autopsy/timeline/ui/detailview/EventNodeBase.java +++ b/Core/src/org/sleuthkit/autopsy/timeline/ui/detailview/EventNodeBase.java @@ -24,15 +24,12 @@ import com.google.common.collect.Sets; import com.google.common.eventbus.Subscribe; import java.util.Arrays; import java.util.Collection; -import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Optional; -import java.util.Set; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ExecutionException; import java.util.logging.Level; -import java.util.stream.Collectors; import javafx.animation.KeyFrame; import javafx.animation.KeyValue; import javafx.animation.Timeline; @@ -82,9 +79,7 @@ import static org.sleuthkit.autopsy.timeline.ui.detailview.EventNodeBase.show; import static org.sleuthkit.autopsy.timeline.ui.detailview.MultiEventNodeBase.CORNER_RADII_3; import org.sleuthkit.autopsy.timeline.ui.detailview.datamodel.DetailViewEvent; import org.sleuthkit.datamodel.SleuthkitCase; -import org.sleuthkit.datamodel.TskCoreException; import org.sleuthkit.datamodel.TimelineEventType; -import org.sleuthkit.datamodel.TimelineEvent; /** * diff --git a/Core/src/org/sleuthkit/autopsy/timeline/ui/filtering/datamodel/RootFilterState.java b/Core/src/org/sleuthkit/autopsy/timeline/ui/filtering/datamodel/RootFilterState.java index d33a32ed21..e3c8b8d6d5 100755 --- a/Core/src/org/sleuthkit/autopsy/timeline/ui/filtering/datamodel/RootFilterState.java +++ b/Core/src/org/sleuthkit/autopsy/timeline/ui/filtering/datamodel/RootFilterState.java @@ -161,18 +161,6 @@ public class RootFilterState extends CompoundFilterState> getSubFilterStates() { ImmutableMap, Integer> filterOrder From ba24db42ba632c395300972bc68e6e6749886c8c Mon Sep 17 00:00:00 2001 From: Mark McKinnon Date: Wed, 18 Sep 2019 09:24:38 -0400 Subject: [PATCH 20/24] Update ArtifactSelectionDialog.java Fix index out of bounds error --- .../autopsy/report/ArtifactSelectionDialog.java | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/report/ArtifactSelectionDialog.java b/Core/src/org/sleuthkit/autopsy/report/ArtifactSelectionDialog.java index b0655dfa2b..4ab05a11aa 100644 --- a/Core/src/org/sleuthkit/autopsy/report/ArtifactSelectionDialog.java +++ b/Core/src/org/sleuthkit/autopsy/report/ArtifactSelectionDialog.java @@ -54,7 +54,7 @@ public class ArtifactSelectionDialog extends javax.swing.JDialog { /** * Creates new form ArtifactSelectionDialog - * + * * @param parent The parent window * @param modal Block user-input to other top-level windows. */ @@ -110,9 +110,11 @@ public class ArtifactSelectionDialog extends javax.swing.JDialog { @Override public void mousePressed(MouseEvent evt) { int index = artifactList.locationToIndex(evt.getPoint()); - BlackboardArtifact.Type type = model.getElementAt(index); - artifactTypeSelections.put(type, !artifactTypeSelections.get(type)); - artifactList.repaint(); + if (index >= 0) { + BlackboardArtifact.Type type = model.getElementAt(index); + artifactTypeSelections.put(type, !artifactTypeSelections.get(type)); + artifactList.repaint(); + } } }); } From 3a50acb90003e728ae45036b9f87c7fda578f670 Mon Sep 17 00:00:00 2001 From: Kelly Kelly Date: Wed, 18 Sep 2019 10:42:39 -0400 Subject: [PATCH 21/24] cleaned up ContactNode --- .../autopsy/communications/relationships/ContactNode.java | 4 ---- 1 file changed, 4 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/communications/relationships/ContactNode.java b/Core/src/org/sleuthkit/autopsy/communications/relationships/ContactNode.java index 462bb6f8fa..985351ce10 100755 --- a/Core/src/org/sleuthkit/autopsy/communications/relationships/ContactNode.java +++ b/Core/src/org/sleuthkit/autopsy/communications/relationships/ContactNode.java @@ -116,10 +116,6 @@ final class ContactNode extends BlackboardArtifactNode { sheetSet.put(new NodeProperty<>(bba.getAttributeType().getTypeName(), bba.getAttributeType().getDisplayName(), "", bba.getDisplayString())); } - // Don't need these values to appear in the Contact property sheet. - sheetSet.remove("S"); - sheetSet.remove("C"); - List children = artifact.getChildren(); if(children != null) { int count = 0; From 7e3199cd8e630ac43d8ba36ea4cdd84fee12a46a Mon Sep 17 00:00:00 2001 From: "U-BASIS\\dsmyda" Date: Wed, 18 Sep 2019 11:12:54 -0400 Subject: [PATCH 22/24] Fixed typo for postgres table names --- test/script/tskdbdiff.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/script/tskdbdiff.py b/test/script/tskdbdiff.py index 5518c97512..baab8573df 100644 --- a/test/script/tskdbdiff.py +++ b/test/script/tskdbdiff.py @@ -430,8 +430,8 @@ def normalize_db_entry(line, files_table, vs_parts_table, vs_info_table, fs_info report_index = line.find('INSERT INTO "reports"') > -1 or line.find('INSERT INTO reports ') > -1 layout_index = line.find('INSERT INTO "tsk_file_layout"') > -1 or line.find('INSERT INTO tsk_file_layout ') > -1 data_source_info_index = line.find('INSERT INTO "data_source_info"') > -1 or line.find('INSERT INTO data_source_info ') > -1 - event_description_index = line.find('INSERT INTO "tsk_event_descriptions"') > -1 or line.find('INSERT INTO data_source_info ') > -1 - events_index = line.find('INSERT INTO "tsk_events"') > -1 or line.find('INSERT INTO data_source_info ') > -1 + event_description_index = line.find('INSERT INTO "tsk_event_descriptions"') > -1 or line.find('INSERT INTO tsk_event_descriptions ') > -1 + events_index = line.find('INSERT INTO "tsk_events"') > -1 or line.find('INSERT INTO tsk_events ') > -1 ingest_job_index = line.find('INSERT INTO "ingest_jobs"') > -1 or line.find('INSERT INTO ingest_jobs ') > -1 examiners_index = line.find('INSERT INTO "tsk_examiners"') > -1 or line.find('INSERT INTO tsk_examiners ') > -1 ig_groups_index = line.find('INSERT INTO "image_gallery_groups"') > -1 or line.find('INSERT INTO image_gallery_groups ') > -1 From 716e0227dd00891475aa4914d18551973f12385a Mon Sep 17 00:00:00 2001 From: Mark McKinnon Date: Wed, 18 Sep 2019 11:58:00 -0400 Subject: [PATCH 23/24] Update FileViewer.java Add check if abstract is file and ignore if it is. --- Core/src/org/sleuthkit/autopsy/contentviewers/FileViewer.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/contentviewers/FileViewer.java b/Core/src/org/sleuthkit/autopsy/contentviewers/FileViewer.java index dddf0f6296..1b0d048f35 100644 --- a/Core/src/org/sleuthkit/autopsy/contentviewers/FileViewer.java +++ b/Core/src/org/sleuthkit/autopsy/contentviewers/FileViewer.java @@ -117,7 +117,7 @@ public class FileViewer extends javax.swing.JPanel implements DataContentViewer } AbstractFile file = selectedNode.getLookup().lookup(AbstractFile.class); - if (file == null) { + if ((file == null) || (file.isDir())) { return; } @@ -189,7 +189,7 @@ public class FileViewer extends javax.swing.JPanel implements DataContentViewer } AbstractFile aFile = node.getLookup().lookup(AbstractFile.class); - if (aFile == null) { + if ((aFile == null) || (aFile.isDir())) { return false; } From a53f0957a066f78d4cb221fcd32997cba0938992 Mon Sep 17 00:00:00 2001 From: Richard Cordovano Date: Wed, 18 Sep 2019 15:02:50 -0400 Subject: [PATCH 24/24] Update Autopsy version number to 4.13.0 --- docs/doxygen-user/Doxyfile | 4 ++-- docs/doxygen/Doxyfile | 4 ++-- nbproject/project.properties | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/docs/doxygen-user/Doxyfile b/docs/doxygen-user/Doxyfile index 7991a0cd95..1bb3773a70 100644 --- a/docs/doxygen-user/Doxyfile +++ b/docs/doxygen-user/Doxyfile @@ -38,7 +38,7 @@ PROJECT_NAME = "Autopsy User Documentation" # could be handy for archiving the generated documentation or if some version # control system is used. -PROJECT_NUMBER = 4.12.0 +PROJECT_NUMBER = 4.13.0 # Using the PROJECT_BRIEF tag one can provide an optional one line description # for a project that appears at the top of each page and should give viewer a @@ -1025,7 +1025,7 @@ GENERATE_HTML = YES # The default directory is: html. # This tag requires that the tag GENERATE_HTML is set to YES. -HTML_OUTPUT = 4.12.0 +HTML_OUTPUT = 4.13.0 # The HTML_FILE_EXTENSION tag can be used to specify the file extension for each # generated HTML page (for example: .htm, .php, .asp). diff --git a/docs/doxygen/Doxyfile b/docs/doxygen/Doxyfile index bf66159b48..b640c41549 100644 --- a/docs/doxygen/Doxyfile +++ b/docs/doxygen/Doxyfile @@ -38,7 +38,7 @@ PROJECT_NAME = "Autopsy" # could be handy for archiving the generated documentation or if some version # control system is used. -PROJECT_NUMBER = 4.12.0 +PROJECT_NUMBER = 4.13.0 # Using the PROJECT_BRIEF tag one can provide an optional one line description # for a project that appears a the top of each page and should give viewer a @@ -1063,7 +1063,7 @@ GENERATE_HTML = YES # The default directory is: html. # This tag requires that the tag GENERATE_HTML is set to YES. -HTML_OUTPUT = api-docs/4.12.0/ +HTML_OUTPUT = api-docs/4.13.0/ # The HTML_FILE_EXTENSION tag can be used to specify the file extension for each # generated HTML page (for example: .htm, .php, .asp). diff --git a/nbproject/project.properties b/nbproject/project.properties index 5d59189544..8132096d48 100644 --- a/nbproject/project.properties +++ b/nbproject/project.properties @@ -4,7 +4,7 @@ app.title=Autopsy ### lowercase version of above app.name=${branding.token} ### if left unset, version will default to today's date -app.version=4.12.0 +app.version=4.13.0 ### build.type must be one of: DEVELOPMENT, RELEASE #build.type=RELEASE build.type=DEVELOPMENT