mirror of
https://github.com/overcuriousity/autopsy-flatpak.git
synced 2025-07-12 16:06:15 +00:00
Extended tag display and filtering to keyword and hash set hits and prohibited making local copies of unalloc/virt files for reports
This commit is contained in:
parent
7bbc5e0a22
commit
ffed632b16
@ -609,40 +609,54 @@ public class Tags implements AutopsyVisitableItem {
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Looks up the tag names associated with an artifact.
|
||||
* Looks up the tag names associated with either a tagged artifact or a tag artifact.
|
||||
*
|
||||
* @param artifact The artifact
|
||||
* @return A set of unique tag names
|
||||
*/
|
||||
public static HashSet<String> getUniqueTagNames(BlackboardArtifact artifact) {
|
||||
HashSet<String> tagNames = new HashSet<>();
|
||||
return getUniqueTagNames(artifact.getArtifactID(), artifact.getArtifactTypeID());
|
||||
}
|
||||
|
||||
List<BlackboardArtifact> tags;
|
||||
/**
|
||||
* Looks up the tag names associated with either a tagged artifact or a tag artifact.
|
||||
*
|
||||
* @param artifactID The ID of the artifact
|
||||
* @param artifactTypeID The ID of the artifact type
|
||||
* @return A set of unique tag names
|
||||
*/
|
||||
public static HashSet<String> getUniqueTagNames(long artifactID, int artifactTypeID) {
|
||||
HashSet<String> tagNames = new HashSet<>();
|
||||
|
||||
try {
|
||||
if (artifact.getArtifactTypeID() == ARTIFACT_TYPE.TSK_TAG_FILE.getTypeID() ||
|
||||
artifact.getArtifactTypeID() == ARTIFACT_TYPE.TSK_TAG_ARTIFACT.getTypeID()) {
|
||||
tags = new ArrayList<>();
|
||||
tags.add(artifact);
|
||||
ArrayList<Long> tagArtifactIDs = new ArrayList<>();
|
||||
if (artifactTypeID == ARTIFACT_TYPE.TSK_TAG_FILE.getTypeID() ||
|
||||
artifactTypeID == ARTIFACT_TYPE.TSK_TAG_ARTIFACT.getTypeID()) {
|
||||
tagArtifactIDs.add(artifactID);
|
||||
} else {
|
||||
tags = Case.getCurrentCase().getSleuthkitCase().getBlackboardArtifacts(ATTRIBUTE_TYPE.TSK_TAGGED_ARTIFACT, artifact.getArtifactID());
|
||||
List<BlackboardArtifact> tags = Case.getCurrentCase().getSleuthkitCase().getBlackboardArtifacts(ATTRIBUTE_TYPE.TSK_TAGGED_ARTIFACT, artifactID);
|
||||
for (BlackboardArtifact tag : tags) {
|
||||
tagArtifactIDs.add(tag.getArtifactID());
|
||||
}
|
||||
}
|
||||
|
||||
for (BlackboardArtifact tag : tags) {
|
||||
String whereClause = "WHERE artifact_id=" + tag.getArtifactID() + " AND attribute_type_id=" + ATTRIBUTE_TYPE.TSK_TAG_NAME.getTypeID();
|
||||
for (Long tagArtifactID : tagArtifactIDs) {
|
||||
String whereClause = "WHERE artifact_id = " + tagArtifactID + " AND attribute_type_id = " + ATTRIBUTE_TYPE.TSK_TAG_NAME.getTypeID();
|
||||
List<BlackboardAttribute> attributes = Case.getCurrentCase().getSleuthkitCase().getMatchingAttributes(whereClause);
|
||||
for (BlackboardAttribute attr : attributes) {
|
||||
tagNames.add(attr.getValueString());
|
||||
}
|
||||
}
|
||||
} catch (TskCoreException ex) {
|
||||
logger.log(Level.SEVERE, "Failed to get tags for artifact " + artifact.getArtifactID(), ex);
|
||||
}
|
||||
catch (TskCoreException ex) {
|
||||
logger.log(Level.SEVERE, "Failed to get tags for artifact " + artifactID, ex);
|
||||
}
|
||||
|
||||
|
||||
return tagNames;
|
||||
}
|
||||
|
||||
|
||||
public interface Taggable {
|
||||
void createTag(String name, String comment);
|
||||
}
|
||||
|
@ -82,7 +82,7 @@ public class ReportGenerator {
|
||||
private ReportGenerationPanel panel = new ReportGenerationPanel();
|
||||
|
||||
static final String REPORTS_DIR = "Reports";
|
||||
|
||||
|
||||
ReportGenerator(Map<TableReportModule, Boolean> tableModuleStates, Map<GeneralReportModule, Boolean> generalModuleStates) {
|
||||
// Setup the reporting directory to be [CASE DIRECTORY]/Reports/[Case name] [Timestamp]/
|
||||
DateFormat dateFormat = new SimpleDateFormat("MM-dd-yyyy-HH-mm-ss");
|
||||
@ -97,8 +97,8 @@ public class ReportGenerator {
|
||||
}
|
||||
|
||||
// Initialize the progress panels
|
||||
generalProgress = new HashMap<GeneralReportModule, ReportProgressPanel>();
|
||||
tableProgress = new HashMap<TableReportModule, ReportProgressPanel>();
|
||||
generalProgress = new HashMap<>();
|
||||
tableProgress = new HashMap<>();
|
||||
setupProgressPanels(tableModuleStates, generalModuleStates);
|
||||
}
|
||||
|
||||
@ -171,7 +171,7 @@ public class ReportGenerator {
|
||||
* @param tagSelections the enabled/disabled state of the tags to be included in the report
|
||||
*/
|
||||
public void generateArtifactTableReports(Map<ARTIFACT_TYPE, Boolean> artifactTypeSelections, Map<String, Boolean> tagSelections) {
|
||||
ArtifactTableReportsWorker worker = new ArtifactTableReportsWorker(artifactTypeSelections, tagSelections);
|
||||
ArtifactsReportsWorker worker = new ArtifactsReportsWorker(artifactTypeSelections, tagSelections);
|
||||
worker.execute();
|
||||
}
|
||||
|
||||
@ -194,21 +194,21 @@ public class ReportGenerator {
|
||||
}
|
||||
|
||||
/**
|
||||
* SwingWorker to use TableReportModules to generate reports on blackboard artifacts.
|
||||
* SwingWorker to generate reports on blackboard artifacts.
|
||||
*/
|
||||
private class ArtifactTableReportsWorker extends SwingWorker<Integer, Integer> {
|
||||
private class ArtifactsReportsWorker extends SwingWorker<Integer, Integer> {
|
||||
List<TableReportModule> tableModules;
|
||||
List<ARTIFACT_TYPE> artifactTypes;
|
||||
HashSet<String> tagNamesFilter;
|
||||
|
||||
// Create an ArtifactWorker with the enabled/disabled state of all Artifacts
|
||||
ArtifactTableReportsWorker(Map<ARTIFACT_TYPE, Boolean> artifactTypeSelections, Map<String, Boolean> tagSelections) {
|
||||
tableModules = new ArrayList<TableReportModule>();
|
||||
ArtifactsReportsWorker(Map<ARTIFACT_TYPE, Boolean> artifactTypeSelections, Map<String, Boolean> tagSelections) {
|
||||
tableModules = new ArrayList<>();
|
||||
for (Entry<TableReportModule, ReportProgressPanel> entry : tableProgress.entrySet()) {
|
||||
tableModules.add(entry.getKey());
|
||||
}
|
||||
|
||||
artifactTypes = new ArrayList<ARTIFACT_TYPE>();
|
||||
artifactTypes = new ArrayList<>();
|
||||
for (Entry<ARTIFACT_TYPE, Boolean> entry : artifactTypeSelections.entrySet()) {
|
||||
if (entry.getValue()) {
|
||||
artifactTypes.add(entry.getKey());
|
||||
@ -216,7 +216,7 @@ public class ReportGenerator {
|
||||
}
|
||||
|
||||
if (tagSelections != null) {
|
||||
tagNamesFilter = new HashSet<String>();
|
||||
tagNamesFilter = new HashSet<>();
|
||||
for (Entry<String, Boolean> entry : tagSelections.entrySet()) {
|
||||
if (entry.getValue() == true) {
|
||||
tagNamesFilter.add(entry.getKey());
|
||||
@ -254,10 +254,10 @@ public class ReportGenerator {
|
||||
|
||||
// If the type is keyword hit or hashset hit, use the helper
|
||||
if (type.equals(ARTIFACT_TYPE.TSK_KEYWORD_HIT)) {
|
||||
writeKeywordHits(tableModules);
|
||||
writeKeywordHits(tableModules, tagNamesFilter);
|
||||
continue;
|
||||
} else if (type.equals(ARTIFACT_TYPE.TSK_HASHSET_HIT)) {
|
||||
writeHashsetHits(tableModules);
|
||||
writeHashsetHits(tableModules, tagNamesFilter);
|
||||
continue;
|
||||
}
|
||||
|
||||
@ -292,7 +292,6 @@ public class ReportGenerator {
|
||||
|
||||
module.startDataType(type.getDisplayName());
|
||||
|
||||
// This is a temporary expedient pending modification of the TableReportModule API.
|
||||
if (module instanceof ReportHTML) {
|
||||
ReportHTML htmlReportModule = (ReportHTML)module;
|
||||
htmlReportModule.startTable(columnHeaders, type);
|
||||
@ -306,12 +305,8 @@ public class ReportGenerator {
|
||||
for (Entry<BlackboardArtifact, List<BlackboardAttribute>> artifactEntry : unsortedArtifacts) {
|
||||
// Get any tags associated with the artifact and apply the tags filter, if any.
|
||||
HashSet<String> tags = Tags.getUniqueTagNames(artifactEntry.getKey());
|
||||
if (tagNamesFilter != null) {
|
||||
HashSet<String> filteredTags = new HashSet<>(tags);
|
||||
filteredTags.retainAll(tagNamesFilter);
|
||||
if (filteredTags.isEmpty()) {
|
||||
continue;
|
||||
}
|
||||
if (failsTagFilter(tags, tagNamesFilter)) {
|
||||
continue;
|
||||
}
|
||||
String tagsList = makeCommaSeparatedList(tags);
|
||||
|
||||
@ -328,7 +323,6 @@ public class ReportGenerator {
|
||||
rowData.add(tagsList);
|
||||
}
|
||||
|
||||
// This is a temporary expedient pending modification of the TableReportModule API.
|
||||
if (module instanceof ReportHTML) {
|
||||
ReportHTML htmlReportModule = (ReportHTML)module;
|
||||
htmlReportModule.addRow(rowData, artifactEntry.getKey());
|
||||
@ -357,12 +351,23 @@ public class ReportGenerator {
|
||||
}
|
||||
}
|
||||
|
||||
private Boolean failsTagFilter(HashSet<String> tags, HashSet<String> tagsFilter)
|
||||
{
|
||||
if (tagsFilter == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
HashSet<String> filteredTags = new HashSet<>(tags);
|
||||
filteredTags.retainAll(tagsFilter);
|
||||
return filteredTags.isEmpty();
|
||||
}
|
||||
|
||||
/**
|
||||
* Write the keyword hits to the provided TableReportModules.
|
||||
* @param tableModules modules to report on
|
||||
*/
|
||||
@SuppressWarnings("deprecation")
|
||||
private void writeKeywordHits(List<TableReportModule> tableModules) {
|
||||
private void writeKeywordHits(List<TableReportModule> tableModules, HashSet<String> tagNamesFilter) {
|
||||
ResultSet listsRs = null;
|
||||
try {
|
||||
// Query for keyword lists
|
||||
@ -403,7 +408,7 @@ public class ReportGenerator {
|
||||
ResultSet rs = null;
|
||||
try {
|
||||
// Query for keywords
|
||||
rs = skCase.runQuery("SELECT art.obj_id, att1.value_text AS keyword, att2.value_text AS preview, att3.value_text AS list, f.name AS name " +
|
||||
rs = skCase.runQuery("SELECT art.artifact_id, art.obj_id, att1.value_text AS keyword, att2.value_text AS preview, att3.value_text AS list, f.name AS name " +
|
||||
"FROM blackboard_artifacts AS art, blackboard_attributes AS att1, blackboard_attributes AS att2, blackboard_attributes AS att3, tsk_files AS f " +
|
||||
"WHERE (att1.artifact_id = art.artifact_id) " +
|
||||
"AND (att2.artifact_id = art.artifact_id) " +
|
||||
@ -428,14 +433,21 @@ public class ReportGenerator {
|
||||
iter.remove();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Get any tags that associated with this artifact and apply the tag filter.
|
||||
HashSet<String> tags = Tags.getUniqueTagNames(rs.getLong("artifact_id"), ARTIFACT_TYPE.TSK_KEYWORD_HIT.getTypeID());
|
||||
if (failsTagFilter(tags, tagNamesFilter)) {
|
||||
continue;
|
||||
}
|
||||
String tagsList = makeCommaSeparatedList(tags);
|
||||
|
||||
Long objId = rs.getLong("obj_id");
|
||||
String keyword = rs.getString("keyword");
|
||||
String preview = rs.getString("preview");
|
||||
String list = rs.getString("list");
|
||||
String uniquePath = "";
|
||||
|
||||
try {
|
||||
|
||||
try {
|
||||
uniquePath = skCase.getAbstractFileById(objId).getUniquePath();
|
||||
} catch (TskCoreException ex) {
|
||||
logger.log(Level.WARNING, "Failed to get Abstract File by ID.", ex);
|
||||
@ -470,9 +482,10 @@ public class ReportGenerator {
|
||||
module.startTable(getArtifactTableColumnHeaders(ARTIFACT_TYPE.TSK_KEYWORD_HIT.getTypeID()));
|
||||
}
|
||||
}
|
||||
|
||||
String previewreplace = EscapeUtil.escapeHtml(preview);
|
||||
for (TableReportModule module : tableModules) {
|
||||
module.addRow(Arrays.asList(new String[] {previewreplace.replaceAll("<!", ""), uniquePath}));
|
||||
module.addRow(Arrays.asList(new String[] {previewreplace.replaceAll("<!", ""), uniquePath, tagsList}));
|
||||
}
|
||||
}
|
||||
|
||||
@ -498,7 +511,7 @@ public class ReportGenerator {
|
||||
* @param tableModules modules to report on
|
||||
*/
|
||||
@SuppressWarnings("deprecation")
|
||||
private void writeHashsetHits(List<TableReportModule> tableModules) {
|
||||
private void writeHashsetHits(List<TableReportModule> tableModules, HashSet<String> tagNamesFilter) {
|
||||
ResultSet listsRs = null;
|
||||
try {
|
||||
// Query for hashsets
|
||||
@ -534,7 +547,7 @@ public class ReportGenerator {
|
||||
ResultSet rs = null;
|
||||
try {
|
||||
// Query for hashset hits
|
||||
rs = skCase.runQuery("SELECT art.obj_id, att.value_text AS setname, f.name AS name, f.size AS size " +
|
||||
rs = skCase.runQuery("SELECT art.artifact_id, art.obj_id, att.value_text AS setname, f.name AS name, f.size AS size " +
|
||||
"FROM blackboard_artifacts AS art, blackboard_attributes AS att, tsk_files AS f " +
|
||||
"WHERE (att.artifact_id = art.artifact_id) " +
|
||||
"AND (f.obj_id = art.obj_id) " +
|
||||
@ -555,6 +568,13 @@ public class ReportGenerator {
|
||||
}
|
||||
}
|
||||
|
||||
// Get any tags that associated with this artifact and apply the tag filter.
|
||||
HashSet<String> tags = Tags.getUniqueTagNames(rs.getLong("artifact_id"), ARTIFACT_TYPE.TSK_HASHSET_HIT.getTypeID());
|
||||
if (failsTagFilter(tags, tagNamesFilter)) {
|
||||
continue;
|
||||
}
|
||||
String tagsList = makeCommaSeparatedList(tags);
|
||||
|
||||
Long objId = rs.getLong("obj_id");
|
||||
String set = rs.getString("setname");
|
||||
String size = rs.getString("size");
|
||||
@ -586,7 +606,7 @@ public class ReportGenerator {
|
||||
|
||||
// Add a row for this hit to every module
|
||||
for (TableReportModule module : tableModules) {
|
||||
module.addRow(Arrays.asList(new String[] {uniquePath, size}));
|
||||
module.addRow(Arrays.asList(new String[] {uniquePath, size, tagsList}));
|
||||
}
|
||||
}
|
||||
|
||||
@ -661,9 +681,7 @@ public class ReportGenerator {
|
||||
}
|
||||
|
||||
if (artifactTypeId != ARTIFACT_TYPE.TSK_TAG_FILE.getTypeID() &&
|
||||
artifactTypeId != ARTIFACT_TYPE.TSK_TAG_ARTIFACT.getTypeID() &&
|
||||
artifactTypeId != ARTIFACT_TYPE.TSK_KEYWORD_HIT.getTypeID() &&
|
||||
artifactTypeId != ARTIFACT_TYPE.TSK_HASHSET_HIT.getTypeID()) {
|
||||
artifactTypeId != ARTIFACT_TYPE.TSK_TAG_ARTIFACT.getTypeID()) {
|
||||
columnHeaders.add("Tags");
|
||||
}
|
||||
|
||||
|
@ -55,6 +55,8 @@ import org.sleuthkit.datamodel.TskCoreException;
|
||||
import org.sleuthkit.datamodel.BlackboardArtifact;
|
||||
import org.sleuthkit.datamodel.BlackboardArtifact.ARTIFACT_TYPE;
|
||||
import org.sleuthkit.datamodel.AbstractFile;
|
||||
import org.sleuthkit.datamodel.TskData;
|
||||
import org.sleuthkit.datamodel.TskData.TSK_DB_FILES_TYPE_ENUM;
|
||||
|
||||
public class ReportHTML implements TableReportModule {
|
||||
private static final Logger logger = Logger.getLogger(ReportHTML.class.getName());
|
||||
@ -144,7 +146,7 @@ public class ReportHTML implements TableReportModule {
|
||||
|
||||
/**
|
||||
* Start a new HTML page for the given data type. Update the output stream to this page,
|
||||
* and setup the webpage header.
|
||||
* and setup the web page header.
|
||||
* @param title title of the data type
|
||||
*/
|
||||
@Override
|
||||
@ -176,7 +178,7 @@ public class ReportHTML implements TableReportModule {
|
||||
}
|
||||
|
||||
/**
|
||||
* End the current data type. Write the end of the webpage and close the
|
||||
* End the current data type. Write the end of the web page and close the
|
||||
* output stream.
|
||||
*/
|
||||
@Override
|
||||
@ -282,6 +284,7 @@ public class ReportHTML implements TableReportModule {
|
||||
|
||||
/**
|
||||
* Start a new table with the given column headers.
|
||||
*
|
||||
* @param columnHeaders column headers
|
||||
* @param sourceArtifact source blackboard artifact for the table data
|
||||
*/
|
||||
@ -294,7 +297,7 @@ public class ReportHTML implements TableReportModule {
|
||||
|
||||
// For file tag artifacts, add a column for a hyperlink to a local copy of the tagged file.
|
||||
if (artifactType.equals(ARTIFACT_TYPE.TSK_TAG_FILE)) {
|
||||
htmlOutput.append("\t\t<th>Local File</th>\n");
|
||||
htmlOutput.append("\t\t<th></th>\n");
|
||||
}
|
||||
|
||||
htmlOutput.append("\t</tr>\n</thead>\n");
|
||||
@ -348,57 +351,7 @@ public class ReportHTML implements TableReportModule {
|
||||
* @param sourceArtifact source blackboard artifact for the table data
|
||||
*/
|
||||
public void addRow(List<String> row, BlackboardArtifact sourceArtifact) {
|
||||
// For file tag artifacts, save a local copy of the tagged file and include a hyperlink to it in the row.
|
||||
if (sourceArtifact.getArtifactTypeID() == ARTIFACT_TYPE.TSK_TAG_FILE.getTypeID()) {
|
||||
try {
|
||||
// Make a folder for the local file with the same name as the tag.
|
||||
StringBuilder localFilePath = new StringBuilder();
|
||||
localFilePath.append(path);
|
||||
HashSet<String> tagNames = Tags.getUniqueTagNames(sourceArtifact);
|
||||
localFilePath.append(tagNames.iterator().next());
|
||||
File tagFolder = new File(localFilePath.toString());
|
||||
if (!tagFolder.exists()) {
|
||||
tagFolder.mkdirs();
|
||||
}
|
||||
|
||||
// Construct a file name for the local file that incorporates the corresponding object id to ensure uniqueness.
|
||||
AbstractFile file = Case.getCurrentCase().getSleuthkitCase().getAbstractFileById(sourceArtifact.getObjectID());
|
||||
String fileName = file.getName();
|
||||
String objectIdSuffix = "_" + sourceArtifact.getObjectID();
|
||||
int lastDotIndex = fileName.lastIndexOf(".");
|
||||
if (lastDotIndex != -1 && lastDotIndex != 0) {
|
||||
// The file name has a conventional extension. Insert the object id before the '.' of the extension.
|
||||
fileName = fileName.substring(0, lastDotIndex) + objectIdSuffix + fileName.substring(lastDotIndex, fileName.length());
|
||||
}
|
||||
else {
|
||||
// The file has no extension or the only '.' in the file is an initial '.', as in a hidden file.
|
||||
// Add the object id to the end of the file name.
|
||||
fileName += objectIdSuffix;
|
||||
}
|
||||
localFilePath.append(File.separator);
|
||||
localFilePath.append(fileName);
|
||||
|
||||
// If the local file doesn't already exist, create it now.
|
||||
// The existence check is necessary because it is possible to apply multiple tags with the same name to a file.
|
||||
File localFile = new File(localFilePath.toString());
|
||||
if (!localFile.exists()) {
|
||||
ExtractFscContentVisitor.extract(file, localFile, null, null);
|
||||
}
|
||||
|
||||
// Add the hyperlink to the row. A column header for it was created in startTable().
|
||||
StringBuilder localFileLink = new StringBuilder();
|
||||
localFileLink.append("<a href=\"file:///");
|
||||
localFileLink.append(localFilePath.toString());
|
||||
localFileLink.append("\">");
|
||||
localFileLink.append(localFilePath.toString());
|
||||
localFileLink.append("</a>");
|
||||
row.add(localFileLink.toString());
|
||||
}
|
||||
catch (TskCoreException ex) {
|
||||
logger.log(Level.WARNING, "Failed to get AbstractFile by ID.", ex);
|
||||
row.add("");
|
||||
}
|
||||
}
|
||||
addRowDataForSourceArtifact(row, sourceArtifact);
|
||||
|
||||
StringBuilder builder = new StringBuilder();
|
||||
builder.append("\t<tr>\n");
|
||||
@ -419,6 +372,89 @@ public class ReportHTML implements TableReportModule {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Add cells particular to a type of artifact associated with the row. Assumes that the overload of startTable() that takes an artifact type was called.
|
||||
*
|
||||
* @param row The row.
|
||||
* @param sourceArtifact The artifact associated with the row.
|
||||
*/
|
||||
private void addRowDataForSourceArtifact(List<String> row, BlackboardArtifact sourceArtifact) {
|
||||
int artifactTypeID = sourceArtifact.getArtifactTypeID();
|
||||
switch (artifactTypeID) {
|
||||
case 17:
|
||||
addRowDataForFileTagArtifact(row, sourceArtifact);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Saves a local copy of a tagged file and adds a hyper link to the file to the row.
|
||||
*
|
||||
* @param row The row.
|
||||
* @param sourceArtifact The artifact associated with the row.
|
||||
*/
|
||||
private void addRowDataForFileTagArtifact(List<String> row, BlackboardArtifact sourceArtifact) {
|
||||
try {
|
||||
AbstractFile file = Case.getCurrentCase().getSleuthkitCase().getAbstractFileById(sourceArtifact.getObjectID());
|
||||
|
||||
// Don't make a local copy of the file if it is unallocated space or a virtual directory.
|
||||
if (file.getType() == TSK_DB_FILES_TYPE_ENUM.UNALLOC_BLOCKS ||
|
||||
file.getType() == TSK_DB_FILES_TYPE_ENUM.UNUSED_BLOCKS ||
|
||||
file.getType() == TSK_DB_FILES_TYPE_ENUM.VIRTUAL_DIR) {
|
||||
row.add("");
|
||||
return;
|
||||
}
|
||||
|
||||
// Make a folder for the local file with the same name as the tag.
|
||||
StringBuilder localFilePath = new StringBuilder();
|
||||
localFilePath.append(path);
|
||||
HashSet<String> tagNames = Tags.getUniqueTagNames(sourceArtifact);
|
||||
if (!tagNames.isEmpty()) {
|
||||
localFilePath.append(tagNames.iterator().next());
|
||||
}
|
||||
File localFileFolder = new File(localFilePath.toString());
|
||||
if (!localFileFolder.exists()) {
|
||||
localFileFolder.mkdirs();
|
||||
}
|
||||
|
||||
// Construct a file name for the local file that incorporates the corresponding object id to ensure uniqueness.
|
||||
String fileName = file.getName();
|
||||
String objectIdSuffix = "_" + sourceArtifact.getObjectID();
|
||||
int lastDotIndex = fileName.lastIndexOf(".");
|
||||
if (lastDotIndex != -1 && lastDotIndex != 0) {
|
||||
// The file name has a conventional extension. Insert the object id before the '.' of the extension.
|
||||
fileName = fileName.substring(0, lastDotIndex) + objectIdSuffix + fileName.substring(lastDotIndex, fileName.length());
|
||||
}
|
||||
else {
|
||||
// The file has no extension or the only '.' in the file is an initial '.', as in a hidden file.
|
||||
// Add the object id to the end of the file name.
|
||||
fileName += objectIdSuffix;
|
||||
}
|
||||
localFilePath.append(File.separator);
|
||||
localFilePath.append(fileName);
|
||||
|
||||
// If the local file doesn't already exist, create it now.
|
||||
// The existence check is necessary because it is possible to apply multiple tags with the same name to a file.
|
||||
File localFile = new File(localFilePath.toString());
|
||||
if (!localFile.exists()) {
|
||||
ExtractFscContentVisitor.extract(file, localFile, null, null);
|
||||
}
|
||||
|
||||
// Add the hyperlink to the row. A column header for it was created in startTable().
|
||||
StringBuilder localFileLink = new StringBuilder();
|
||||
localFileLink.append("<a href=\"file:///");
|
||||
localFileLink.append(localFilePath.toString());
|
||||
localFileLink.append("\">View File</a>");
|
||||
row.add(localFileLink.toString());
|
||||
}
|
||||
catch (TskCoreException ex) {
|
||||
logger.log(Level.WARNING, "Failed to get AbstractFile by ID.", ex);
|
||||
row.add("");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a String date for the long date given.
|
||||
* @param date date as a long
|
||||
|
Loading…
x
Reference in New Issue
Block a user