mirror of
https://github.com/overcuriousity/autopsy-flatpak.git
synced 2025-07-12 07:56:16 +00:00
Merge branch 'release-4.13.0' of https://github.com/sleuthkit/autopsy into 5446-file-transfer-apps
This commit is contained in:
commit
71c47a40f9
@ -0,0 +1,49 @@
|
||||
/*
|
||||
* Autopsy Forensic Browser
|
||||
*
|
||||
* Copyright 2019 Basis Technology Corp.
|
||||
* Contact: carrier <at> sleuthkit <dot> org
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.sleuthkit.autopsy.casemodule;
|
||||
|
||||
import java.io.File;
|
||||
import java.nio.file.Paths;
|
||||
import org.sleuthkit.autopsy.coreutils.PlatformUtil;
|
||||
|
||||
/**
|
||||
* Class for methods to check if access should be limited to a feature
|
||||
*
|
||||
*/
|
||||
final class AccessLimiterUtils {
|
||||
|
||||
private final static String MULTI_USER_ACCESS_FILE_NAME = "mualimit"; // NON-NLS
|
||||
private final static String MULTI_USER_ACCESS_FILE_PATH = Paths.get(PlatformUtil.getUserConfigDirectory(), MULTI_USER_ACCESS_FILE_NAME).toString();
|
||||
|
||||
/**
|
||||
* Check if privileges regarding multi-user cases should be restricted.
|
||||
*
|
||||
* @return True if privileges should be restricted, false otherwise.
|
||||
*/
|
||||
static boolean limitMultiUserAccess() {
|
||||
return new File(MULTI_USER_ACCESS_FILE_PATH).exists();
|
||||
}
|
||||
|
||||
/**
|
||||
* Private constructor for a utility class
|
||||
*/
|
||||
private AccessLimiterUtils() {
|
||||
//private constructer left empty intentionally
|
||||
}
|
||||
}
|
@ -1049,7 +1049,7 @@ public class Case {
|
||||
/*
|
||||
* Enable the case-specific actions.
|
||||
*/
|
||||
CallableSystemAction.get(AddImageAction.class).setEnabled(true);
|
||||
CallableSystemAction.get(AddImageAction.class).setEnabled(Case.getCurrentCase().getMetadata().getCaseType() == CaseType.SINGLE_USER_CASE || !AccessLimiterUtils.limitMultiUserAccess());
|
||||
CallableSystemAction.get(CaseCloseAction.class).setEnabled(true);
|
||||
CallableSystemAction.get(CaseDetailsAction.class).setEnabled(true);
|
||||
CallableSystemAction.get(DataSourceSummaryAction.class).setEnabled(true);
|
||||
|
@ -61,7 +61,7 @@ final class NewCaseVisualPanel1 extends JPanel implements DocumentListener {
|
||||
*/
|
||||
void readSettings() {
|
||||
caseNameTextField.setText("");
|
||||
if (UserPreferences.getIsMultiUserModeEnabled()) {
|
||||
if (UserPreferences.getIsMultiUserModeEnabled() && !AccessLimiterUtils.limitMultiUserAccess()) {
|
||||
multiUserCaseRadioButton.setEnabled(true);
|
||||
multiUserCaseRadioButton.setSelected(true);
|
||||
} else {
|
||||
|
@ -29,6 +29,7 @@ import java.nio.file.Paths;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.logging.Level;
|
||||
@ -198,7 +199,8 @@ final class AddLogicalImageTask implements Runnable {
|
||||
}
|
||||
|
||||
List<Content> newDataSources = new ArrayList<>();
|
||||
|
||||
Map<String, List<Long>> interestingFileMap = new HashMap<>();
|
||||
|
||||
if (imagePaths.isEmpty()) {
|
||||
createVHD = false;
|
||||
// No VHD in src directory, try ingest the root directory as local files
|
||||
@ -214,7 +216,7 @@ final class AddLogicalImageTask implements Runnable {
|
||||
|
||||
try {
|
||||
progressMonitor.setProgressText(Bundle.AddLogicalImageTask_addingExtractedFiles());
|
||||
addExtractedFiles(dest, resultsPath, newDataSources);
|
||||
interestingFileMap = addExtractedFiles(dest, resultsPath, newDataSources);
|
||||
progressMonitor.setProgressText(Bundle.AddLogicalImageTask_doneAddingExtractedFiles());
|
||||
} catch (IOException | TskCoreException ex) {
|
||||
errorList.add(ex.getMessage());
|
||||
@ -241,6 +243,14 @@ final class AddLogicalImageTask implements Runnable {
|
||||
callback.done(DataSourceProcessorCallback.DataSourceProcessorResult.CRITICAL_ERRORS, addMultipleImagesTask.getErrorMessages(), emptyDataSources);
|
||||
return;
|
||||
}
|
||||
try {
|
||||
interestingFileMap = getInterestingFileMapForVHD(Paths.get(dest.toString(), resultsFilename));
|
||||
} catch (TskCoreException | IOException ex) {
|
||||
errorList.add(Bundle.AddLogicalImageTask_failedToAddInterestingFiles(ex.getMessage()));
|
||||
LOGGER.log(Level.SEVERE, "Failed to add interesting files", ex); // NON-NLS
|
||||
callback.done(DataSourceProcessorCallback.DataSourceProcessorResult.NONCRITICAL_ERRORS, errorList, emptyDataSources);
|
||||
}
|
||||
|
||||
} catch (NoCurrentCaseException ex) {
|
||||
String msg = Bundle.AddLogicalImageTask_noCurrentCase();
|
||||
errorList.add(msg);
|
||||
@ -261,7 +271,7 @@ final class AddLogicalImageTask implements Runnable {
|
||||
|
||||
try {
|
||||
progressMonitor.setProgressText(Bundle.AddLogicalImageTask_addingInterestingFiles());
|
||||
addInterestingFiles(Paths.get(dest.toString(), resultsFilename), createVHD);
|
||||
addInterestingFiles(interestingFileMap);
|
||||
progressMonitor.setProgressText(Bundle.AddLogicalImageTask_doneAddingInterestingFiles());
|
||||
if (createVHD) {
|
||||
callback.done(addMultipleImagesTask.getResult(), addMultipleImagesTask.getErrorMessages(), addMultipleImagesTask.getNewDataSources());
|
||||
@ -332,13 +342,67 @@ final class AddLogicalImageTask implements Runnable {
|
||||
"# {0} - target image path", "AddLogicalImageTask.cannotFindDataSourceObjId=Cannot find obj_id in tsk_image_names for {0}",
|
||||
"# {0} - file number", "# {1} - total files", "AddLogicalImageTask.addingInterestingFile=Adding interesting files ({0}/{1})"
|
||||
})
|
||||
private void addInterestingFiles(Path resultsPath, boolean createVHD) throws IOException, TskCoreException {
|
||||
private void addInterestingFiles(Map<String, List<Long>> interestingFileMap) throws IOException, TskCoreException {
|
||||
int lineNumber = 0;
|
||||
List<BlackboardArtifact> artifacts = new ArrayList<>();
|
||||
|
||||
Iterator<Map.Entry<String, List<Long>>> iterator = interestingFileMap.entrySet().iterator();
|
||||
while (iterator.hasNext()) {
|
||||
|
||||
if (cancelled) {
|
||||
// Don't delete destination directory once we started adding interesting files.
|
||||
// At this point the database and destination directory are complete.
|
||||
break;
|
||||
}
|
||||
|
||||
Map.Entry<String, List<Long>> entry = iterator.next();
|
||||
String key = entry.getKey();
|
||||
String ruleSetName;
|
||||
String ruleName;
|
||||
String[] split = key.split("\t");
|
||||
ruleSetName = split[0];
|
||||
ruleName = split[1];
|
||||
|
||||
List<Long> fileIds = entry.getValue();
|
||||
for (Long fileId: fileIds) {
|
||||
if (lineNumber % 100 == 0) {
|
||||
progressMonitor.setProgressText(Bundle.AddLogicalImageTask_addingInterestingFile(lineNumber, totalFiles));
|
||||
}
|
||||
addInterestingFileToArtifacts(fileId, ruleSetName, ruleName, artifacts);
|
||||
lineNumber++;
|
||||
}
|
||||
iterator.remove();
|
||||
}
|
||||
|
||||
try {
|
||||
// index the artifact for keyword search
|
||||
blackboard.postArtifacts(artifacts, MODULE_NAME);
|
||||
} catch (Blackboard.BlackboardException ex) {
|
||||
LOGGER.log(Level.SEVERE, "Unable to post artifacts to blackboard", ex); //NON-NLS
|
||||
}
|
||||
}
|
||||
|
||||
private void addInterestingFileToArtifacts(long fileId, String ruleSetName, String ruleName, List<BlackboardArtifact> artifacts) throws TskCoreException {
|
||||
Collection<BlackboardAttribute> attributes = new ArrayList<>();
|
||||
BlackboardAttribute setNameAttribute = new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_SET_NAME, MODULE_NAME, ruleSetName);
|
||||
attributes.add(setNameAttribute);
|
||||
BlackboardAttribute ruleNameAttribute = new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_CATEGORY, MODULE_NAME, ruleName);
|
||||
attributes.add(ruleNameAttribute);
|
||||
BlackboardArtifact artifact = this.currentCase.getSleuthkitCase().newBlackboardArtifact(BlackboardArtifact.ARTIFACT_TYPE.TSK_INTERESTING_FILE_HIT, fileId);
|
||||
artifact.addAttributes(attributes);
|
||||
artifacts.add(artifact);
|
||||
}
|
||||
|
||||
@Messages({
|
||||
"# {0} - file number", "# {1} - total files", "AddLogicalImageTask.searchingInterestingFile=Searching for interesting files ({0}/{1})"
|
||||
})
|
||||
private Map<String, List<Long>> getInterestingFileMapForVHD(Path resultsPath) throws TskCoreException, IOException {
|
||||
Map<Long, List<String>> objIdToimagePathsMap = currentCase.getSleuthkitCase().getImagePaths();
|
||||
imagePathToObjIdMap = imagePathsToDataSourceObjId(objIdToimagePathsMap);
|
||||
|
||||
Map<String, List<Long>> interestingFileMap = new HashMap<>();
|
||||
|
||||
try (BufferedReader br = new BufferedReader(new InputStreamReader(
|
||||
new FileInputStream(resultsPath.toFile()), "UTF8"))) { // NON-NLS
|
||||
List<BlackboardArtifact> artifacts = new ArrayList<>();
|
||||
String line;
|
||||
br.readLine(); // skip the header line
|
||||
int lineNumber = 2;
|
||||
@ -363,47 +427,35 @@ final class AddLogicalImageTask implements Runnable {
|
||||
String parentPath = fields[8];
|
||||
|
||||
if (lineNumber % 100 == 0) {
|
||||
progressMonitor.setProgressText(Bundle.AddLogicalImageTask_addingInterestingFile(lineNumber, totalFiles));
|
||||
progressMonitor.setProgressText(Bundle.AddLogicalImageTask_searchingInterestingFile(lineNumber, totalFiles));
|
||||
}
|
||||
String query = makeQuery(createVHD, vhdFilename, fileMetaAddressStr, parentPath, filename);
|
||||
|
||||
// TODO - findAllFilesWhere should SQL-escape the query
|
||||
String query = makeQuery(vhdFilename, fileMetaAddressStr, parentPath, filename);
|
||||
List<AbstractFile> matchedFiles = Case.getCurrentCase().getSleuthkitCase().findAllFilesWhere(query);
|
||||
List<Long> fileIds = new ArrayList<>();
|
||||
for (AbstractFile file : matchedFiles) {
|
||||
addInterestingFileToArtifacts(file, ruleSetName, ruleName, artifacts);
|
||||
fileIds.add(file.getId());
|
||||
}
|
||||
String key = String.format("%s\t%s", ruleSetName, ruleName);
|
||||
if (interestingFileMap.containsKey(key)) {
|
||||
interestingFileMap.get(key).addAll(fileIds);
|
||||
} else {
|
||||
interestingFileMap.put(key, fileIds);
|
||||
}
|
||||
lineNumber++;
|
||||
} // end reading file
|
||||
|
||||
try {
|
||||
// index the artifact for keyword search
|
||||
blackboard.postArtifacts(artifacts, MODULE_NAME);
|
||||
} catch (Blackboard.BlackboardException ex) {
|
||||
LOGGER.log(Level.SEVERE, "Unable to post artifacts to blackboard", ex); //NON-NLS
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void addInterestingFileToArtifacts(AbstractFile file, String ruleSetName, String ruleName, List<BlackboardArtifact> artifacts) throws TskCoreException {
|
||||
Collection<BlackboardAttribute> attributes = new ArrayList<>();
|
||||
BlackboardAttribute setNameAttribute = new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_SET_NAME, MODULE_NAME, ruleSetName);
|
||||
attributes.add(setNameAttribute);
|
||||
BlackboardAttribute ruleNameAttribute = new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_CATEGORY, MODULE_NAME, ruleName);
|
||||
attributes.add(ruleNameAttribute);
|
||||
if (!blackboard.artifactExists(file, BlackboardArtifact.ARTIFACT_TYPE.TSK_INTERESTING_FILE_HIT, attributes)) {
|
||||
BlackboardArtifact artifact = this.currentCase.getSleuthkitCase().newBlackboardArtifact(BlackboardArtifact.ARTIFACT_TYPE.TSK_INTERESTING_FILE_HIT, file.getId());
|
||||
artifact.addAttributes(attributes);
|
||||
artifacts.add(artifact);
|
||||
} // end reading file }
|
||||
}
|
||||
return interestingFileMap;
|
||||
}
|
||||
|
||||
@Messages({
|
||||
"# {0} - file number", "# {1} - total files", "AddLogicalImageTask.addingExtractedFile=Adding extracted files ({0}/{1})"
|
||||
})
|
||||
private void addExtractedFiles(File src, Path resultsPath, List<Content> newDataSources) throws TskCoreException, IOException {
|
||||
private Map<String, List<Long>> addExtractedFiles(File src, Path resultsPath, List<Content> newDataSources) throws TskCoreException, IOException {
|
||||
SleuthkitCase skCase = Case.getCurrentCase().getSleuthkitCase();
|
||||
SleuthkitCase.CaseDbTransaction trans = null;
|
||||
|
||||
Map<String, List<Long>> interestingFileMap = new HashMap<>();
|
||||
|
||||
try {
|
||||
trans = skCase.beginTransaction();
|
||||
LocalFilesDataSource localFilesDataSource = skCase.addLocalFilesDataSource(deviceId, this.src.getName(), timeZone, trans);
|
||||
@ -417,7 +469,7 @@ final class AddLogicalImageTask implements Runnable {
|
||||
while ((line = br.readLine()) != null) {
|
||||
if (cancelled) {
|
||||
rollbackTransaction(trans);
|
||||
return;
|
||||
return new HashMap<>();
|
||||
}
|
||||
String[] fields = line.split("\t", -1); // NON-NLS
|
||||
if (fields.length != 14) {
|
||||
@ -428,8 +480,8 @@ final class AddLogicalImageTask implements Runnable {
|
||||
// String fileSystemOffsetStr = fields[1];
|
||||
// String fileMetaAddressStr = fields[2];
|
||||
// String extractStatusStr = fields[3];
|
||||
// String ruleSetName = fields[4];
|
||||
// String ruleName = fields[5];
|
||||
String ruleSetName = fields[4];
|
||||
String ruleName = fields[5];
|
||||
// String description = fields[6];
|
||||
String filename = fields[7];
|
||||
String parentPath = fields[8];
|
||||
@ -445,7 +497,7 @@ final class AddLogicalImageTask implements Runnable {
|
||||
}
|
||||
|
||||
//addLocalFile here
|
||||
fileImporter.addLocalFile(
|
||||
AbstractFile fileAdded = fileImporter.addLocalFile(
|
||||
Paths.get(src.toString(), extractedFilePath).toFile(),
|
||||
filename,
|
||||
parentPath,
|
||||
@ -454,12 +506,19 @@ final class AddLogicalImageTask implements Runnable {
|
||||
Long.parseLong(atime),
|
||||
Long.parseLong(mtime),
|
||||
localFilesDataSource);
|
||||
|
||||
String key = String.format("%s\t%s", ruleSetName, ruleName);
|
||||
List<Long> value = new ArrayList<>();
|
||||
if (interestingFileMap.containsKey(key)) {
|
||||
value = interestingFileMap.get(key);
|
||||
}
|
||||
value.add(fileAdded.getId());
|
||||
interestingFileMap.put(key, value);
|
||||
lineNumber++;
|
||||
} // end reading file
|
||||
}
|
||||
trans.commit();
|
||||
newDataSources.add(localFilesDataSource);
|
||||
return interestingFileMap;
|
||||
|
||||
} catch (NumberFormatException | TskCoreException ex) {
|
||||
LOGGER.log(Level.SEVERE, "Error adding extracted files", ex); // NON-NLS
|
||||
@ -489,21 +548,16 @@ final class AddLogicalImageTask implements Runnable {
|
||||
}
|
||||
}
|
||||
|
||||
String makeQuery(boolean createVHD, String vhdFilename, String fileMetaAddressStr, String parentPath, String filename) throws TskCoreException {
|
||||
String makeQuery(String vhdFilename, String fileMetaAddressStr, String parentPath, String filename) throws TskCoreException {
|
||||
String query;
|
||||
if (createVHD) {
|
||||
String targetImagePath = Paths.get(dest.toString(), vhdFilename).toString();
|
||||
Long dataSourceObjId = imagePathToObjIdMap.get(targetImagePath);
|
||||
if (dataSourceObjId == null) {
|
||||
throw new TskCoreException(Bundle.AddLogicalImageTask_cannotFindDataSourceObjId(targetImagePath));
|
||||
}
|
||||
query = String.format("data_source_obj_id = '%s' AND meta_addr = '%s' AND name = '%s'", // NON-NLS
|
||||
dataSourceObjId.toString(), fileMetaAddressStr, filename.replace("'", "''"));
|
||||
} else {
|
||||
String newParentPath = "/" + ROOT_STR + "/" + vhdFilename + "/" + parentPath;
|
||||
query = String.format("name = '%s' AND parent_path = '%s'", // NON-NLS
|
||||
filename.replace("'", "''"), newParentPath.replace("'", "''"));
|
||||
String targetImagePath = Paths.get(dest.toString(), vhdFilename).toString();
|
||||
Long dataSourceObjId = imagePathToObjIdMap.get(targetImagePath);
|
||||
if (dataSourceObjId == null) {
|
||||
throw new TskCoreException(Bundle.AddLogicalImageTask_cannotFindDataSourceObjId(targetImagePath));
|
||||
}
|
||||
query = String.format("data_source_obj_id = '%s' AND meta_addr = '%s' AND name = '%s'", // NON-NLS
|
||||
dataSourceObjId.toString(), fileMetaAddressStr, filename.replace("'", "''"));
|
||||
// TODO - findAllFilesWhere should SQL-escape the query
|
||||
return query;
|
||||
}
|
||||
|
||||
|
@ -46,6 +46,9 @@ AddLogicalImageTask.noCurrentCase=No current case
|
||||
# {1} - fields length
|
||||
# {2} - expected length
|
||||
AddLogicalImageTask.notEnoughFields=File does not contain enough fields at line {0}, got {1}, expecting {2}
|
||||
# {0} - file number
|
||||
# {1} - total files
|
||||
AddLogicalImageTask.searchingInterestingFile=Searching for interesting files ({0}/{1})
|
||||
# {0} - imageFilePath
|
||||
AddMultipleImagesTask.adding=Adding: {0}
|
||||
# {0} - file
|
||||
|
@ -770,8 +770,11 @@ final public class ViewFrame extends BorderPane {
|
||||
Notifications.create().owner(getScene().getWindow())
|
||||
.text(Bundle.ViewFrame_pickerListener_errorMessage())
|
||||
.showError();
|
||||
logger.log(Level.SEVERE, "Error responding to date/time picker change.", ex);
|
||||
logger.log(Level.WARNING, "Error responding to date/time picker change.", ex); //NON-NLS
|
||||
} catch (IllegalArgumentException ex ) {
|
||||
logger.log(Level.INFO, "Timeline: User supplied invalid time range."); //NON-NLS
|
||||
}
|
||||
|
||||
Platform.runLater(ViewFrame.this::refreshTimeUI);
|
||||
}
|
||||
}
|
||||
|
@ -192,33 +192,29 @@ The first question that you must answer is what type of data do you want the use
|
||||
-# Data that is in a big text file or some other report that the user can review. To do this, you will use the Case.addReport() method to make the output available in the directory tree.
|
||||
|
||||
|
||||
\subsection ingest_modules_making_results_bb Posting Results to the Blackboard
|
||||
\subsection ingest_modules_making_results_bb Saving Results to the Blackboard
|
||||
The blackboard is used to store results so that they are displayed in the results tree.
|
||||
See \ref platform_blackboard for details on posting results to it. You use the blackboard when you have specific items to show the user. if you want to just shown them a big report from another library or tool, see \ref mod_report_page.
|
||||
See \ref platform_blackboard for details on saving results to it. You use the blackboard when you have specific items to show the user. If you want to just shown them a big report from another library or tool, see \ref mod_report_page.
|
||||
The blackboard defines artifacts for specific data types (such as web bookmarks).
|
||||
You can use one of the standard artifact types or create your own.
|
||||
|
||||
When modules add data to the blackboard, they should notify listeners of the new
|
||||
data by invoking the org.sleuthkit.autopsy.ingest.IngestServices.fireModuleDataEvent() method.
|
||||
Do so as soon as you have added an artifact to the blackboard.
|
||||
This allows other modules (and the main UI) to know when to query the blackboard
|
||||
for the latest data. However, if you are writing a large number of blackboard
|
||||
artifacts in a loop, it is better to invoke org.sleuthkit.autopsy.ingest.IngestServices.fireModuleDataEvent()
|
||||
only once after the bulk write, so as not to flood the system with events.
|
||||
After you've added an artifact and all of its attributes to the blackboard, you should call <a href="http://sleuthkit.org/sleuthkit/docs/jni-docs/4.6/classorg_1_1sleuthkit_1_1datamodel_1_1_blackboard.html">sleuthkit.Blackboard.postArtifact()</a>, which will:
|
||||
<ul>
|
||||
<li>Analyze the artifact and add any timestamps to the Timeline tables
|
||||
<li>Send an event over the Sleuth Kit event bus that the artifact(s) was added
|
||||
<ul>
|
||||
<li>Autopsy is a listener of this event bus and will rebroadcast the event to other Autopsy modules
|
||||
<li>Keyword search also listens for this event and will index the artifact
|
||||
</ul>
|
||||
</ul>
|
||||
|
||||
Further, when modules create artifacts, they should be indexed for keyword search,
|
||||
using the method org.sleuthkit.autopsy.casemodule.services.Blackboard.indexArtifact(BlackboardArtifact artifact). This can be done
|
||||
in the following way:
|
||||
|
||||
\code
|
||||
Blackboard blackboard = Case.getCurrentCase().getServices().getBlackboard();
|
||||
try {
|
||||
blackboard.indexArtifact(artifact); //Your artifact as the argument.
|
||||
}
|
||||
catch (BlackboardException ex) {
|
||||
//YOUR EXCEPTION BEHAVIOR HERE.
|
||||
}
|
||||
\endcode
|
||||
This means you no longer have to make separate calls to:
|
||||
- Index the artifact
|
||||
- Fire the event to refresh the UI.
|
||||
|
||||
If you are creating a large number of artifacts, you may see better performance if you save all the artifacts you create and do one bulk post at the end using <a href="http://sleuthkit.org/sleuthkit/docs/jni-docs/4.6/classorg_1_1sleuthkit_1_1datamodel_1_1_blackboard.html">sleuthkit.Blackboard.postArtifacts()</a>. You can also post batches of artifacts instead of saving all of them until the end.
|
||||
|
||||
You should not be using the Autopsy version of Blackboard. Those methods have all been deprecated and is another example of us moving "services" into the TSK data model.
|
||||
|
||||
|
||||
\subsection ingest_modules_making_results_report Making a Report
|
||||
|
@ -52,7 +52,7 @@ The blackboard allows modules to communicate with each other and the UI. It has
|
||||
|
||||
The blackboard is not unique to Autopsy. It is part of The Sleuth Kit datamodel and The Sleuth Kit Framework. In the name of reducing the amount of documentation that we need to maintain, we provide links here to those documentation sources.
|
||||
|
||||
- <a href="http://sleuthkit.org/sleuthkit/docs/jni-docs/4.3/mod_bbpage.html">The Blackboard</a>
|
||||
- <a href="http://sleuthkit.org/sleuthkit/docs/jni-docs/4.6/mod_bbpage.html">The Blackboard</a>
|
||||
|
||||
|
||||
\subsection mod_dev_other_services Framework Services and Utilities
|
||||
|
@ -224,8 +224,6 @@ final class VcardParser {
|
||||
if (!tskBlackboard.artifactExists(abstractFile, BlackboardArtifact.ARTIFACT_TYPE.TSK_CONTACT, attributes)) {
|
||||
artifact = abstractFile.newArtifact(BlackboardArtifact.ARTIFACT_TYPE.TSK_CONTACT);
|
||||
artifact.addAttributes(attributes);
|
||||
List<BlackboardArtifact> blackboardArtifacts = new ArrayList<>();
|
||||
blackboardArtifacts.add(artifact);
|
||||
|
||||
extractPhotos(vcard, abstractFile, artifact);
|
||||
|
||||
@ -388,8 +386,12 @@ final class VcardParser {
|
||||
*/
|
||||
private void addPhoneAttributes(Telephone telephone, AbstractFile abstractFile, Collection<BlackboardAttribute> attributes) {
|
||||
String telephoneText = telephone.getText();
|
||||
|
||||
if (telephoneText == null || telephoneText.isEmpty()) {
|
||||
return;
|
||||
telephoneText = telephone.getUri().getNumber();
|
||||
if (telephoneText == null || telephoneText.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Add phone number to collection for later creation of TSK_CONTACT.
|
||||
@ -408,20 +410,25 @@ final class VcardParser {
|
||||
type.getValue().toUpperCase().replaceAll("\\s+","").split(","));
|
||||
|
||||
for (String splitType : splitTelephoneTypes) {
|
||||
String attributeTypeName = "TSK_PHONE_NUMBER_" + splitType;
|
||||
String attributeTypeName = "TSK_PHONE_NUMBER";
|
||||
if(splitType != null && !splitType.isEmpty()) {
|
||||
attributeTypeName = "TSK_PHONE_NUMBER_" + splitType;
|
||||
}
|
||||
|
||||
try {
|
||||
BlackboardAttribute.Type attributeType = tskCase.getAttributeType(attributeTypeName);
|
||||
if (attributeType == null) {
|
||||
// Add this attribute type to the case database.
|
||||
attributeType = tskCase.addArtifactAttributeType(attributeTypeName,
|
||||
BlackboardAttribute.TSK_BLACKBOARD_ATTRIBUTE_VALUE_TYPE.STRING,
|
||||
String.format("Phone (%s)", StringUtils.capitalize(splitType.toLowerCase())));
|
||||
attributeType = tskCase.addArtifactAttributeType(attributeTypeName,
|
||||
BlackboardAttribute.TSK_BLACKBOARD_ATTRIBUTE_VALUE_TYPE.STRING,
|
||||
String.format("Phone Number (%s)", StringUtils.capitalize(splitType.toLowerCase())));
|
||||
|
||||
}
|
||||
ThunderbirdMboxFileIngestModule.addArtifactAttribute(telephone.getText(), attributeType, attributes);
|
||||
ThunderbirdMboxFileIngestModule.addArtifactAttribute(telephoneText, attributeType, attributes);
|
||||
} catch (TskCoreException ex) {
|
||||
logger.log(Level.SEVERE, String.format("Unable to retrieve attribute type '%s' for file '%s' (id=%d).", attributeTypeName, abstractFile.getName(), abstractFile.getId()), ex);
|
||||
logger.log(Level.WARNING, String.format("Unable to retrieve attribute type '%s' for file '%s' (id=%d).", attributeTypeName, abstractFile.getName(), abstractFile.getId()), ex);
|
||||
} catch (TskDataException ex) {
|
||||
logger.log(Level.SEVERE, String.format("Unable to add custom attribute type '%s' for file '%s' (id=%d).", attributeTypeName, abstractFile.getName(), abstractFile.getId()), ex);
|
||||
logger.log(Level.WARNING, String.format("Unable to add custom attribute type '%s' for file '%s' (id=%d).", attributeTypeName, abstractFile.getName(), abstractFile.getId()), ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -490,7 +497,11 @@ final class VcardParser {
|
||||
private void addPhoneAccountInstances(Telephone telephone, AbstractFile abstractFile, Collection<AccountFileInstance> accountInstances) {
|
||||
String telephoneText = telephone.getText();
|
||||
if (telephoneText == null || telephoneText.isEmpty()) {
|
||||
return;
|
||||
telephoneText = telephone.getUri().getNumber();
|
||||
if (telephoneText == null || telephoneText.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// Add phone number as a TSK_ACCOUNT.
|
||||
|
Loading…
x
Reference in New Issue
Block a user