Merge branch 'develop' of github.com:sleuthkit/autopsy into 7505-tempPathChanges

This commit is contained in:
Greg DiCristofaro 2021-04-14 11:27:47 -04:00
commit 02e2f952de
32 changed files with 733 additions and 226 deletions

View File

@ -1,3 +1,4 @@
CTL_ResetWindowsAction=Reset Windows
ResetWindowAction.confirm.text=The program will close and restart to perform the resetting of window locations.\n\nAre you sure you want to reset all window locations?
ResetWindowAction.confirm.title=Reset Windows
ResetWindowAction.caseCloseFailure.text=Unable to close the current case, the software will restart and the windows locations will reset the next time the software is closed.
ResetWindowAction.caseSaveMetadata.text=Unable to save current case path, the software will restart and the windows locations will reset but the current case will not be opened upon restart.
ResetWindowAction.confirm.text=In order to perform the resetting of window locations the software will close and restart. If a case is currently open, it will be closed. If ingest or a search is currently running, it will be terminated. Are you sure you want to restart the software to reset all window locations?

View File

@ -20,8 +20,8 @@ package org.sleuthkit.autopsy.apputils;
import java.io.File;
import java.io.IOException;
import java.nio.charset.Charset;
import java.util.logging.Level;
import javax.swing.JOptionPane;
import javax.swing.SwingUtilities;
import org.apache.commons.io.FileUtils;
import org.openide.LifecycleManager;
@ -32,9 +32,10 @@ import org.openide.awt.ActionRegistration;
import org.openide.util.HelpCtx;
import org.openide.util.NbBundle;
import org.openide.util.actions.CallableSystemAction;
import org.openide.windows.WindowManager;
import org.sleuthkit.autopsy.casemodule.Case;
import org.sleuthkit.autopsy.casemodule.CaseActionException;
import org.sleuthkit.autopsy.coreutils.Logger;
import org.sleuthkit.autopsy.coreutils.MessageNotifyUtil;
import org.sleuthkit.autopsy.coreutils.PlatformUtil;
/**
@ -51,46 +52,74 @@ public final class ResetWindowsAction extends CallableSystemAction {
private static final String DISPLAY_NAME = Bundle.CTL_ResetWindowsAction();
private static final long serialVersionUID = 1L;
private final static Logger logger = Logger.getLogger(ResetWindowsAction.class.getName());
private final static String WINDOWS2LOCAL = "Windows2Local";
private final static String CASE_TO_REOPEN_FILE = "caseToOpen.txt";
@Override
public boolean isEnabled() {
return !Case.isCaseOpen();
return true;
}
@NbBundle.Messages({"ResetWindowAction.confirm.title=Reset Windows",
"ResetWindowAction.confirm.text=The program will close and restart to perform the resetting of window locations.\n\nAre you sure you want to reset all window locations?"})
@NbBundle.Messages({"ResetWindowAction.confirm.text=In order to perform the resetting of window locations the software will close and restart. "
+ "If a case is currently open, it will be closed. If ingest or a search is currently running, it will be terminated. "
+ "Are you sure you want to restart the software to reset all window locations?",
"ResetWindowAction.caseCloseFailure.text=Unable to close the current case, "
+ "the software will restart and the windows locations will reset the next time the software is closed.",
"ResetWindowAction.caseSaveMetadata.text=Unable to save current case path, "
+ "the software will restart and the windows locations will reset but the current case will not be opened upon restart."})
@Override
public void performAction() {
SwingUtilities.invokeLater(() -> {
int response = JOptionPane.showConfirmDialog(
WindowManager.getDefault().getMainWindow(),
Bundle.ResetWindowAction_confirm_text(),
Bundle.ResetWindowAction_confirm_title(),
JOptionPane.YES_NO_OPTION, JOptionPane.PLAIN_MESSAGE);
if (response == JOptionPane.YES_OPTION) {
boolean response = MessageNotifyUtil.Message.confirm(Bundle.ResetWindowAction_confirm_text());
if (response) {
//adding the shutdown hook, closing the current case, and marking for restart can be re-ordered if slightly different behavior is desired
Runtime.getRuntime().addShutdownHook(new Thread() {
@Override
public void run() {
try {
FileUtils.deleteDirectory(new File(PlatformUtil.getUserConfigDirectory() + File.separator + "Windows2Local"));
FileUtils.deleteDirectory(new File(PlatformUtil.getUserConfigDirectory() + File.separator + WINDOWS2LOCAL));
} catch (IOException ex) {
logger.log(Level.WARNING, "Unable to delete config directory, window locations will not be reset.", ex);
//While we would like the user to be aware of this in the unlikely event that the directory can not be deleted
//Because our deletion is being attempted in a shutdown hook I don't know that we can pop up UI elements during the shutdown proces
logger.log(Level.SEVERE, "Unable to delete config directory, window locations will not be reset. To manually reset the windows please delete the following directory while the software is closed. " + PlatformUtil.getUserConfigDirectory() + File.separator + "Windows2Local", ex);
}
}
});
try {
if (Case.isCaseOpen()) {
String caseMetadataFilePath = Case.getCurrentCase().getMetadata().getFilePath().toString();
File caseToOpenFile = new File(ResetWindowsAction.getCaseToReopenFilePath());
Charset encoding = null; //prevents writeStringToFile from having ambiguous arguments
FileUtils.writeStringToFile(caseToOpenFile, caseMetadataFilePath, encoding);
Case.closeCurrentCase();
}
// The method markForRestart can not be undone once it is called.
LifecycleManager.getDefault().markForRestart();
//we need to call exit last
LifecycleManager.getDefault().exit();
} catch (CaseActionException ex) {
logger.log(Level.WARNING, Bundle.ResetWindowAction_caseCloseFailure_text(), ex);
MessageNotifyUtil.Message.show(Bundle.ResetWindowAction_caseCloseFailure_text(), MessageNotifyUtil.MessageType.ERROR);
} catch (IOException ex) {
logger.log(Level.WARNING, Bundle.ResetWindowAction_caseSaveMetadata_text(), ex);
MessageNotifyUtil.Message.show(Bundle.ResetWindowAction_caseSaveMetadata_text(), MessageNotifyUtil.MessageType.ERROR);
}
}
});
}
public static String getCaseToReopenFilePath(){
return PlatformUtil.getUserConfigDirectory() + File.separator + CASE_TO_REOPEN_FILE;
}
/**
* Set this action to be enabled/disabled
*
* @param value whether to enable this action or not
*/
@Override
public void setEnabled(boolean value) {
super.setEnabled(value);
}

View File

@ -346,6 +346,12 @@ RecentCases.getName.text=Clear Recent Cases
RecentItems.openRecentCase.msgDlg.text=Case {0} no longer exists.
SelectDataSourceProcessorPanel.name.text=Select Data Source Type
StartupWindow.title.text=Welcome
# {0} - autFilePath
StartupWindowProvider.openCase.cantOpen=Unable to open previously open case with metadata file: {0}
# {0} - reOpenFilePath
StartupWindowProvider.openCase.deleteOpenFailure=Unable to open or delete file containing path {0} to previously open case. The previous case will not be opened.
# {0} - autFilePath
StartupWindowProvider.openCase.noFile=Unable to open previously open case because metadata file not found at: {0}
UnpackagePortableCaseDialog.title.text=Unpackage Portable Case
UnpackagePortableCaseDialog.UnpackagePortableCaseDialog.extensions=Portable case package (.zip, .zip.001)
UnpackagePortableCaseDialog.validatePaths.badExtension=File extension must be .zip or .zip.001

View File

@ -1934,7 +1934,7 @@ public class Case {
*
* @return A CaseMetaData object.
*/
CaseMetadata getMetadata() {
public CaseMetadata getMetadata() {
return metadata;
}

View File

@ -218,7 +218,7 @@ public final class CaseMetadata {
*
* @return The path to the metadata file
*/
Path getFilePath() {
public Path getFilePath() {
return metadataFilePath;
}

View File

@ -284,10 +284,10 @@ public class ImageDSProcessor implements DataSourceProcessor, AutoIngestDataSour
ingestStream = IngestManager.getInstance().openIngestStream(image, settings);
} catch (TskCoreException ex) {
logger.log(Level.SEVERE, "Error starting ingest modules", ex);
final List<String> errors = new ArrayList<>();
errors.add(ex.getMessage());
callBack.done(DataSourceProcessorCallback.DataSourceProcessorResult.CRITICAL_ERRORS, errors, new ArrayList<>());
return;
// There was an error with ingest, but the data source has already been added
// so proceed with the defaultIngestStream. Code in openIngestStream
// should have caused a dialog to popup with the errors.
ingestStream = new DefaultIngestStream();
}
doAddImageProcess(deviceId, imagePath, sectorSize, timeZone, ignoreFatOrphanFiles, md5, sha1, sha256, progress, callBack);

View File

@ -18,12 +18,18 @@
*/
package org.sleuthkit.autopsy.casemodule;
import java.io.File;
import java.io.IOException;
import java.nio.charset.Charset;
import java.util.Collection;
import java.util.Iterator;
import java.util.logging.Level;
import org.netbeans.spi.sendopts.OptionProcessor;
import javax.swing.SwingUtilities;
import org.apache.commons.io.FileUtils;
import org.apache.commons.lang3.StringUtils;
import org.openide.util.Lookup;
import org.openide.util.NbBundle;
import org.sleuthkit.autopsy.apputils.ResetWindowsAction;
import org.sleuthkit.autopsy.commandlineingest.CommandLineIngestManager;
import org.sleuthkit.autopsy.commandlineingest.CommandLineOpenCaseManager;
import org.sleuthkit.autopsy.commandlineingest.CommandLineOptionProcessor;
@ -61,6 +67,13 @@ public class StartupWindowProvider implements StartupWindowInterface {
return instance;
}
@NbBundle.Messages({
"# {0} - autFilePath",
"StartupWindowProvider.openCase.noFile=Unable to open previously open case because metadata file not found at: {0}",
"# {0} - reOpenFilePath",
"StartupWindowProvider.openCase.deleteOpenFailure=Unable to open or delete file containing path {0} to previously open case. The previous case will not be opened.",
"# {0} - autFilePath",
"StartupWindowProvider.openCase.cantOpen=Unable to open previously open case with metadata file: {0}"})
private void init() {
if (startupWindowToUse == null) {
// first check whether we are running from command line
@ -83,37 +96,42 @@ public class StartupWindowProvider implements StartupWindowInterface {
if (RuntimeProperties.runningWithGUI()) {
checkSolr();
}
//discover the registered windows
Collection<? extends StartupWindowInterface> startupWindows
= Lookup.getDefault().lookupAll(StartupWindowInterface.class);
int windowsCount = startupWindows.size();
if (windowsCount == 1) {
switch (windowsCount) {
case 1:
startupWindowToUse = startupWindows.iterator().next();
logger.log(Level.INFO, "Will use the default startup window: " + startupWindowToUse.toString()); //NON-NLS
} else if (windowsCount == 2) {
logger.log(Level.INFO, "Will use the default startup window: {0}", startupWindowToUse.toString()); //NON-NLS
break;
case 2: {
//pick the non default one
Iterator<? extends StartupWindowInterface> it = startupWindows.iterator();
while (it.hasNext()) {
StartupWindowInterface window = it.next();
if (!org.sleuthkit.autopsy.casemodule.StartupWindow.class.isInstance(window)) {
startupWindowToUse = window;
logger.log(Level.INFO, "Will use the custom startup window: " + startupWindowToUse.toString()); //NON-NLS
logger.log(Level.INFO, "Will use the custom startup window: {0}", startupWindowToUse.toString()); //NON-NLS
break;
}
}
} else {
break;
}
default: {
// select first non-Autopsy start up window
Iterator<? extends StartupWindowInterface> it = startupWindows.iterator();
while (it.hasNext()) {
StartupWindowInterface window = it.next();
if (!window.getClass().getCanonicalName().startsWith("org.sleuthkit.autopsy")) {
startupWindowToUse = window;
logger.log(Level.INFO, "Will use the custom startup window: " + startupWindowToUse.toString()); //NON-NLS
logger.log(Level.INFO, "Will use the custom startup window: {0}", startupWindowToUse.toString()); //NON-NLS
break;
}
}
break;
}
}
if (startupWindowToUse == null) {
@ -121,6 +139,45 @@ public class StartupWindowProvider implements StartupWindowInterface {
startupWindowToUse = new org.sleuthkit.autopsy.casemodule.StartupWindow();
}
}
File openPreviousCaseFile = new File(ResetWindowsAction.getCaseToReopenFilePath());
if (openPreviousCaseFile.exists()) {
//do actual opening on another thread
new Thread(() -> {
String caseFilePath = "";
String unableToOpenMessage = null;
try {
//avoid readFileToString having ambiguous arguments
Charset encoding = null;
caseFilePath = FileUtils.readFileToString(openPreviousCaseFile, encoding);
if (new File(caseFilePath).exists()) {
FileUtils.forceDelete(openPreviousCaseFile);
//close the startup window as we attempt to open the case
close();
Case.openAsCurrentCase(caseFilePath);
} else {
unableToOpenMessage = Bundle.StartupWindowProvider_openCase_noFile(caseFilePath);
logger.log(Level.WARNING, unableToOpenMessage);
}
} catch (IOException ex) {
unableToOpenMessage = Bundle.StartupWindowProvider_openCase_deleteOpenFailure(ResetWindowsAction.getCaseToReopenFilePath());
logger.log(Level.WARNING, unableToOpenMessage, ex);
} catch (CaseActionException ex) {
unableToOpenMessage = Bundle.StartupWindowProvider_openCase_cantOpen(caseFilePath);
logger.log(Level.WARNING, unableToOpenMessage, ex);
}
if (RuntimeProperties.runningWithGUI() && !StringUtils.isBlank(unableToOpenMessage)) {
final String message = unableToOpenMessage;
SwingUtilities.invokeLater(() -> {
MessageNotifyUtil.Message.warn(message);
//the case was not opened restore the startup window
open();
});
}
}).start();
}
}
private void checkSolr() {

View File

@ -301,7 +301,7 @@ final class AutopsyOptionsPanel extends javax.swing.JPanel {
/**
* Values for configuration located in the /etc/*.conf file.
* Values for configuration located in the /etc/\*.conf file.
*/
private static class ConfValues {
private final String XmxVal;
@ -335,7 +335,7 @@ final class AutopsyOptionsPanel extends javax.swing.JPanel {
}
/**
* Retrieve the /etc/*.conf file values pertinent to settings.
* Retrieve the /etc/\*.conf file values pertinent to settings.
* @return The conf file values.
* @throws IOException
*/

View File

@ -376,6 +376,10 @@ TagNode.propertySheet.origNameDisplayName=Original Name
TagsNode.displayName.text=Tags
TagsNode.createSheet.name.name=Name
TagsNode.createSheet.name.displayName=Name
UnsupportedContentNode.createSheet.name.desc=no description
UnsupportedContentNode.createSheet.name.displayName=Name
UnsupportedContentNode.createSheet.name.name=Name
UnsupportedContentNode.displayName=Unsupported Content
ViewsNode.name.text=Views
ViewsNode.createSheet.name.name=Name
ViewsNode.createSheet.name.displayName=Name

View File

@ -18,6 +18,8 @@
*/
package org.sleuthkit.autopsy.datamodel;
import org.sleuthkit.autopsy.datamodel.OsAccounts.OsAccountNode;
/**
* Visitor Pattern interface that goes over Content nodes in the data source
* area of the tree.
@ -50,6 +52,9 @@ interface ContentNodeVisitor<T> {
T visit(BlackboardArtifactNode bban);
T visit(UnsupportedContentNode ucn);
T visit(OsAccountNode bban);
/**
* Visitor with an implementable default behavior for all types. Override
@ -122,5 +127,15 @@ interface ContentNodeVisitor<T> {
public T visit(BlackboardArtifactNode bban) {
return defaultVisit(bban);
}
@Override
public T visit(UnsupportedContentNode ucn) {
return defaultVisit(ucn);
}
@Override
public T visit(OsAccountNode bban) {
return defaultVisit(bban);
}
}
}

View File

@ -32,6 +32,7 @@ import org.sleuthkit.datamodel.Pool;
import org.sleuthkit.datamodel.SlackFile;
import org.sleuthkit.datamodel.SleuthkitItemVisitor;
import org.sleuthkit.datamodel.SleuthkitVisitableItem;
import org.sleuthkit.datamodel.UnsupportedContent;
import org.sleuthkit.datamodel.VirtualDirectory;
import org.sleuthkit.datamodel.Volume;
@ -100,6 +101,11 @@ public class CreateSleuthkitNodeVisitor extends SleuthkitItemVisitor.Default<Abs
return new BlackboardArtifactNode(art);
}
@Override
public AbstractContentNode<? extends Content> visit(UnsupportedContent uc) {
return new UnsupportedContentNode(uc);
}
@Override
protected AbstractContentNode<? extends Content> defaultVisit(SleuthkitVisitableItem di) {
throw new UnsupportedOperationException(NbBundle.getMessage(this.getClass(),

View File

@ -203,6 +203,11 @@ public interface DisplayableItemNodeVisitor<T> {
T visit(DataSourcesByTypeNode node);
/*
* Unsupported node
*/
T visit(UnsupportedContentNode ucn);
/**
* Visitor with an implementable default behavior for all types. Override
* specific visit types to not use the default behavior.
@ -574,5 +579,10 @@ public interface DisplayableItemNodeVisitor<T> {
public T visit(PersonGroupingNode node) {
return defaultVisit(node);
}
@Override
public T visit(UnsupportedContentNode node) {
return defaultVisit(node);
}
}
}

View File

@ -20,6 +20,7 @@ package org.sleuthkit.autopsy.datamodel;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.lang.ref.WeakReference;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Arrays;
@ -29,18 +30,26 @@ import java.util.List;
import java.util.Optional;
import java.util.logging.Level;
import javax.swing.Action;
import org.apache.commons.lang3.tuple.Pair;
import org.openide.nodes.ChildFactory;
import org.openide.nodes.Children;
import org.openide.nodes.Node;
import org.openide.nodes.Sheet;
import org.openide.util.Exceptions;
import org.openide.util.NbBundle.Messages;
import org.openide.util.lookup.Lookups;
import org.openide.util.WeakListeners;
import org.sleuthkit.autopsy.casemodule.Case;
import org.sleuthkit.autopsy.casemodule.events.OsAccountChangedEvent;
import org.sleuthkit.autopsy.centralrepository.datamodel.CorrelationAttributeInstance;
import org.sleuthkit.autopsy.corecomponents.DataResultViewerTable;
import org.sleuthkit.autopsy.coreutils.Logger;
import static org.sleuthkit.autopsy.datamodel.AbstractContentNode.backgroundTasksPool;
import org.sleuthkit.autopsy.events.AutopsyEvent;
import org.sleuthkit.datamodel.Host;
import org.sleuthkit.datamodel.OsAccount;
import org.sleuthkit.datamodel.OsAccountRealm;
import org.sleuthkit.datamodel.SleuthkitCase;
import org.sleuthkit.datamodel.Tag;
import org.sleuthkit.datamodel.TskCoreException;
import org.sleuthkit.datamodel.TskDataException;
@ -52,6 +61,7 @@ public final class OsAccounts implements AutopsyVisitableItem {
private static final Logger logger = Logger.getLogger(OsAccounts.class.getName());
private static final String ICON_PATH = "org/sleuthkit/autopsy/images/os-account.png";
private static final SimpleDateFormat DATE_FORMATTER = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss z");
private static final String REALM_DATA_AVAILABLE_EVENT = "REALM_DATA_AVAILABLE_EVENT";
private SleuthkitCase skCase;
private final long filteringDSObjId;
@ -166,35 +176,52 @@ public final class OsAccounts implements AutopsyVisitableItem {
/**
* An OsAccount leaf Node.
*/
public static final class OsAccountNode extends DisplayableItemNode {
public static final class OsAccountNode extends AbstractContentNode<OsAccount> {
private OsAccount account;
private final PropertyChangeListener listener = new PropertyChangeListener() {
@Override
public void propertyChange(PropertyChangeEvent evt) {
if (evt.getPropertyName().equals(Case.Events.OS_ACCOUNT_CHANGED.name())) {
if (((OsAccountChangedEvent) evt).getOsAccount().getId() == account.getId()) {
// Update the account node to the new one
account = ((OsAccountChangedEvent) evt).getOsAccount();
updateSheet();
}
} else if (evt.getPropertyName().equals(REALM_DATA_AVAILABLE_EVENT)) {
OsAccountRealm realm = (OsAccountRealm) evt.getNewValue();
// Currently only 0 or 1 names are supported, this will need
// to be modified if that changes.
List<String> realmNames = realm.getRealmNames();
if (!realmNames.isEmpty()) {
updateSheet(new NodeProperty<>(
Bundle.OsAccounts_accountRealmNameProperty_name(),
Bundle.OsAccounts_accountRealmNameProperty_displayName(),
Bundle.OsAccounts_accountRealmNameProperty_desc(),
""));
}
}
}
};
private final PropertyChangeListener weakListener = WeakListeners.propertyChange(listener, null);
/**
* Constructs a new OsAccountNode.
*
* @param account Node object.
*/
OsAccountNode(OsAccount account) {
super(Children.LEAF, Lookups.fixed(account));
super(account);
this.account = account;
setName(account.getName());
setDisplayName(account.getName());
setIconBaseWithExtension(ICON_PATH);
Case.addEventTypeSubscriber(Collections.singleton(Case.Events.OS_ACCOUNT_CHANGED), listener);
Case.addEventTypeSubscriber(Collections.singleton(Case.Events.OS_ACCOUNT_CHANGED), weakListener);
}
@Override
@ -212,6 +239,15 @@ public final class OsAccounts implements AutopsyVisitableItem {
return getClass().getName();
}
/**
* Returns the OsAccount associated with this node.
*
* @return
*/
OsAccount getOsAccount() {
return account;
}
@Messages({
"OsAccounts_accountNameProperty_name=Name",
"OsAccounts_accountNameProperty_displayName=Name",
@ -255,9 +291,8 @@ public final class OsAccounts implements AutopsyVisitableItem {
Bundle.OsAccounts_loginNameProperty_displayName(),
Bundle.OsAccounts_loginNameProperty_desc(),
optional.isPresent() ? optional.get() : ""));
// TODO - load realm on background thread
// Fill with empty string, fetch on background task.
String realmName = "";
//String realmName = account.getRealm().getRealmNames().isEmpty() ? "" : account.getRealm().getRealmNames().get(0);
propertiesSet.put(new NodeProperty<>(
Bundle.OsAccounts_accountRealmNameProperty_name(),
Bundle.OsAccounts_accountRealmNameProperty_displayName(),
@ -274,6 +309,8 @@ public final class OsAccounts implements AutopsyVisitableItem {
Bundle.OsAccounts_createdTimeProperty_desc(),
timeDisplayStr));
backgroundTasksPool.submit(new GetOsAccountRealmTask(new WeakReference<>(this), weakListener));
return sheet;
}
@ -285,5 +322,78 @@ public final class OsAccounts implements AutopsyVisitableItem {
return actionsList.toArray(new Action[actionsList.size()]);
}
@Override
protected List<Tag> getAllTagsFromDatabase() {
throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
}
@Override
protected CorrelationAttributeInstance getCorrelationAttributeInstance() {
return null;
}
@Override
protected Pair<DataResultViewerTable.Score, String> getScorePropertyAndDescription(List<Tag> tags) {
return null;
}
@Override
protected DataResultViewerTable.HasCommentStatus getCommentProperty(List<Tag> tags, CorrelationAttributeInstance attribute) {
return DataResultViewerTable.HasCommentStatus.NO_COMMENT;
}
@Override
protected Pair<Long, String> getCountPropertyAndDescription(CorrelationAttributeInstance.Type attributeType, String attributeValue, String defaultDescription) {
return null;
}
@Override
public <T> T accept(ContentNodeVisitor<T> visitor) {
return visitor.visit(this);
}
/**
* Task for grabbing the osAccount realm.
*/
static class GetOsAccountRealmTask implements Runnable {
private final WeakReference<OsAccountNode> weakNodeRef;
private final PropertyChangeListener listener;
/**
* Construct a new task.
*
* @param weakContentRef
* @param listener
*/
GetOsAccountRealmTask(WeakReference<OsAccountNode> weakContentRef, PropertyChangeListener listener) {
this.weakNodeRef = weakContentRef;
this.listener = listener;
}
@Override
public void run() {
OsAccountNode node = weakNodeRef.get();
if (node == null) {
return;
}
try {
long realmId = node.getOsAccount().getRealmId();
OsAccountRealm realm = Case.getCurrentCase().getSleuthkitCase().getOsAccountRealmManager().getRealmByRealmId(realmId);
if (listener != null && realm != null) {
listener.propertyChange(new PropertyChangeEvent(
AutopsyEvent.SourceType.LOCAL.toString(),
REALM_DATA_AVAILABLE_EVENT,
null, realm));
}
} catch (TskCoreException ex) {
Exceptions.printStackTrace(ex);
}
}
}
}
}

View File

@ -0,0 +1,186 @@
/*
* Autopsy Forensic Browser
*
* Copyright 2021 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.datamodel;
import java.util.ArrayList;
import java.util.List;
import javax.swing.Action;
import org.apache.commons.lang3.tuple.Pair;
import org.openide.nodes.Sheet;
import org.openide.util.NbBundle;
import org.sleuthkit.autopsy.centralrepository.datamodel.CorrelationAttributeInstance;
import org.sleuthkit.autopsy.corecomponents.DataResultViewerTable;
import static org.sleuthkit.autopsy.datamodel.AbstractContentNode.NO_DESCR;
import org.sleuthkit.datamodel.UnsupportedContent;
import org.sleuthkit.datamodel.Tag;
/**
* This class is used to represent the "Node" for an unsupported content object.
*/
public class UnsupportedContentNode extends AbstractContentNode<UnsupportedContent> {
/**
*
* @param unsupportedContent underlying Content instance
*/
@NbBundle.Messages({
"UnsupportedContentNode.displayName=Unsupported Content",
})
public UnsupportedContentNode(UnsupportedContent unsupportedContent) {
super(unsupportedContent);
// set name, display name, and icon
this.setDisplayName(Bundle.UnsupportedContentNode_displayName());
this.setIconBaseWithExtension("org/sleuthkit/autopsy/images/file-icon.png"); //NON-NLS
}
/**
* Right click action for UnsupportedContentNode node
*
* @param popup
*
* @return
*/
@Override
public Action[] getActions(boolean popup) {
List<Action> actionsList = new ArrayList<>();
for (Action a : super.getActions(true)) {
actionsList.add(a);
}
return actionsList.toArray(new Action[actionsList.size()]);
}
@NbBundle.Messages({
"UnsupportedContentNode.createSheet.name.name=Name",
"UnsupportedContentNode.createSheet.name.displayName=Name",
"UnsupportedContentNode.createSheet.name.desc=no description",
})
@Override
protected Sheet createSheet() {
Sheet sheet = super.createSheet();
Sheet.Set sheetSet = sheet.get(Sheet.PROPERTIES);
if (sheetSet == null) {
sheetSet = Sheet.createPropertiesSet();
sheet.put(sheetSet);
}
sheetSet.put(new NodeProperty<>(Bundle.UnsupportedContentNode_createSheet_name_name(),
Bundle.UnsupportedContentNode_createSheet_name_displayName(),
Bundle.UnsupportedContentNode_createSheet_name_desc(),
this.getDisplayName()));
return sheet;
}
@Override
public <T> T accept(ContentNodeVisitor<T> visitor) {
return visitor.visit(this);
}
@Override
public boolean isLeafTypeNode() {
return false;
}
@Override
public <T> T accept(DisplayableItemNodeVisitor<T> visitor) {
return visitor.visit(this);
}
@Override
public String getItemType() {
return getClass().getName();
}
/**
* Reads and returns a list of all tags associated with this content node.
*
* Null implementation of an abstract method.
*
* @return list of tags associated with the node.
*/
@Override
protected List<Tag> getAllTagsFromDatabase() {
return new ArrayList<>();
}
/**
* Returns correlation attribute instance for the underlying content of the
* node.
*
* Null implementation of an abstract method.
*
* @return correlation attribute instance for the underlying content of the
* node.
*/
@Override
protected CorrelationAttributeInstance getCorrelationAttributeInstance() {
return null;
}
/**
* Returns Score property for the node.
*
* Null implementation of an abstract method.
*
* @param tags list of tags.
*
* @return Score property for the underlying content of the node.
*/
@Override
protected Pair<DataResultViewerTable.Score, String> getScorePropertyAndDescription(List<Tag> tags) {
return Pair.of(DataResultViewerTable.Score.NO_SCORE, NO_DESCR);
}
/**
* Returns comment property for the node.
*
* Null implementation of an abstract method.
*
* @param tags list of tags
* @param attribute correlation attribute instance
*
* @return Comment property for the underlying content of the node.
*/
@Override
protected DataResultViewerTable.HasCommentStatus getCommentProperty(List<Tag> tags, CorrelationAttributeInstance attribute) {
return DataResultViewerTable.HasCommentStatus.NO_COMMENT;
}
/**
* Returns occurrences/count property for the node.
*
* Null implementation of an abstract method.
*
* @param attributeType the type of the attribute to count
* @param attributeValue the value of the attribute to coun
* @param defaultDescription a description to use when none is determined by
* the getCountPropertyAndDescription method
*
* @return count property for the underlying content of the node.
*/
@Override
protected Pair<Long, String> getCountPropertyAndDescription(CorrelationAttributeInstance.Type attributeType, String attributeValue, String defaultDescription) {
return Pair.of(-1L, NO_DESCR);
}
}

View File

@ -59,6 +59,7 @@ SelectionContext.views=Views
ViewContextAction.errorMessage.cannotFindDirectory=Failed to locate directory.
ViewContextAction.errorMessage.cannotFindNode=Failed to locate data source node in tree.
ViewContextAction.errorMessage.cannotSelectDirectory=Failed to select directory in tree.
ViewContextAction.errorMessage.unsupportedParent=Unable to navigate to content not supported in this release.
VolumeDetailsPanel.volumeIDLabel.text=Volume ID:
VolumeDetailsPanel.volumeIDValue.text=...
VolumeDetailsPanel.startValue.text=...

View File

@ -304,7 +304,6 @@ public class DataResultFilterNode extends FilterNode {
NbBundle.getMessage(this.getClass(), "DataResultFilterNode.action.viewFileInDir.text"), c));
}
// action to go to the source file of the artifact
// action to go to the source file of the artifact
Content fileContent = ban.getLookup().lookup(AbstractFile.class);
if (fileContent == null) {
Content content = ban.getLookup().lookup(Content.class);

View File

@ -63,6 +63,7 @@ import org.sleuthkit.datamodel.SleuthkitCase;
import org.sleuthkit.datamodel.TskCoreException;
import org.sleuthkit.datamodel.TskData;
import org.sleuthkit.datamodel.TskDataException;
import org.sleuthkit.datamodel.UnsupportedContent;
import org.sleuthkit.datamodel.VolumeSystem;
/**
@ -161,7 +162,8 @@ public class ViewContextAction extends AbstractAction {
@Messages({
"ViewContextAction.errorMessage.cannotFindDirectory=Failed to locate directory.",
"ViewContextAction.errorMessage.cannotSelectDirectory=Failed to select directory in tree.",
"ViewContextAction.errorMessage.cannotFindNode=Failed to locate data source node in tree."
"ViewContextAction.errorMessage.cannotFindNode=Failed to locate data source node in tree.",
"ViewContextAction.errorMessage.unsupportedParent=Unable to navigate to content not supported in this release."
})
public void actionPerformed(ActionEvent event) {
EventQueue.invokeLater(() -> {
@ -182,6 +184,13 @@ public class ViewContextAction extends AbstractAction {
return;
}
if ((parentContent != null)
&& (parentContent instanceof UnsupportedContent)) {
MessageNotifyUtil.Message.error(Bundle.ViewContextAction_errorMessage_unsupportedParent());
logger.log(Level.WARNING, String.format("Could not navigate to unsupported content with id: %d", parentContent.getId())); //NON-NLS
return;
}
/*
* Get the "Data Sources" node from the tree view.
*/

View File

@ -60,7 +60,7 @@ final class ObjectDetectedFilterPanel extends AbstractDiscoveryFilterPanel {
objectsList.clearList();
List<String> setNames = DiscoveryUiUtils.getSetNames(BlackboardArtifact.ARTIFACT_TYPE.TSK_OBJECT_DETECTED, BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DESCRIPTION);
for (String name : setNames) {
objectsList.addElement(name, null, null);
objectsList.addElement(name, null, name);
}
} catch (TskCoreException ex) {
logger.log(Level.SEVERE, "Error loading object detected set names", ex);

View File

@ -31,6 +31,7 @@ import org.sleuthkit.datamodel.LocalFile;
import org.sleuthkit.datamodel.LocalDirectory;
import org.sleuthkit.datamodel.OsAccount;
import org.sleuthkit.datamodel.SlackFile;
import org.sleuthkit.datamodel.UnsupportedContent;
import org.sleuthkit.datamodel.VirtualDirectory;
/**
@ -113,4 +114,9 @@ final class GetRootDirectoryVisitor extends GetFilesContentVisitor {
public Collection<AbstractFile> visit(OsAccount art) {
return getAllFromChildren(art);
}
@Override
public Collection<AbstractFile> visit(UnsupportedContent uc) {
return getAllFromChildren(uc);
}
}

View File

@ -175,8 +175,8 @@ final class ChromeCacheExtractor {
fileManager = currentCase.getServices().getFileManager();
// Create an output folder to save any derived files
absOutputFolderName = RAImageIngestModule.getRAOutputPath(currentCase, moduleName);
relOutputFolderName = Paths.get( RAImageIngestModule.getRelModuleOutputPath(), moduleName).normalize().toString();
absOutputFolderName = RAImageIngestModule.getRAOutputPath(currentCase, moduleName, context.getJobId());
relOutputFolderName = Paths.get(RAImageIngestModule.getRelModuleOutputPath(currentCase, moduleName, context.getJobId())).normalize().toString();
File dir = new File(absOutputFolderName);
if (dir.exists() == false) {
@ -206,7 +206,7 @@ final class ChromeCacheExtractor {
outDir.mkdirs();
}
String cacheTempPath = RAImageIngestModule.getRATempPath(currentCase, moduleName) + cachePath;
String cacheTempPath = RAImageIngestModule.getRATempPath(currentCase, moduleName, context.getJobId()) + cachePath;
File tempDir = new File(cacheTempPath);
if (tempDir.exists() == false) {
tempDir.mkdirs();
@ -222,7 +222,7 @@ final class ChromeCacheExtractor {
private void cleanup () {
for (Entry<String, FileWrapper> entry : this.fileCopyCache.entrySet()) {
Path tempFilePath = Paths.get(RAImageIngestModule.getRATempPath(currentCase, moduleName), entry.getKey() );
Path tempFilePath = Paths.get(RAImageIngestModule.getRATempPath(currentCase, moduleName, context.getJobId()), entry.getKey() );
try {
entry.getValue().getFileCopy().getChannel().close();
entry.getValue().getFileCopy().close();
@ -652,7 +652,7 @@ final class ChromeCacheExtractor {
// write the file to disk so that we can have a memory-mapped ByteBuffer
AbstractFile cacheFile = abstractFileOptional.get();
RandomAccessFile randomAccessFile = null;
String tempFilePathname = RAImageIngestModule.getRATempPath(currentCase, moduleName) + cacheFolderName + cacheFile.getName(); //NON-NLS
String tempFilePathname = RAImageIngestModule.getRATempPath(currentCase, moduleName, context.getJobId()) + cacheFolderName + cacheFile.getName(); //NON-NLS
try {
File newFile = new File(tempFilePathname);
ContentUtils.writeToFile(cacheFile, newFile, context::dataSourceIngestIsCancelled);

View File

@ -130,42 +130,43 @@ class Chromium extends Extract {
this.dataSource = dataSource;
this.context = context;
dataFound = false;
long ingestJobId = context.getJobId();
for (Map.Entry<String, String> browser : BROWSERS_MAP.entrySet()) {
String browserName = browser.getKey();
String browserLocation = browser.getValue();
progressBar.progress(NbBundle.getMessage(this.getClass(), "Progress_Message_Chrome_History", browserName));
this.getHistory(browser.getKey(), browser.getValue());
this.getHistory(browser.getKey(), browser.getValue(), ingestJobId);
if (context.dataSourceIngestIsCancelled()) {
return;
}
progressBar.progress(NbBundle.getMessage(this.getClass(), "Progress_Message_Chrome_Bookmarks", browserName));
this.getBookmark(browser.getKey(), browser.getValue());
this.getBookmark(browser.getKey(), browser.getValue(), ingestJobId);
if (context.dataSourceIngestIsCancelled()) {
return;
}
progressBar.progress(NbBundle.getMessage(this.getClass(), "Progress_Message_Chrome_Cookies", browserName));
this.getCookie(browser.getKey(), browser.getValue());
this.getCookie(browser.getKey(), browser.getValue(), ingestJobId);
if (context.dataSourceIngestIsCancelled()) {
return;
}
progressBar.progress(NbBundle.getMessage(this.getClass(), "Progress_Message_Chrome_Logins", browserName));
this.getLogins(browser.getKey(), browser.getValue());
this.getLogins(browser.getKey(), browser.getValue(), ingestJobId);
if (context.dataSourceIngestIsCancelled()) {
return;
}
progressBar.progress(NbBundle.getMessage(this.getClass(), "Progress_Message_Chrome_AutoFill", browserName));
this.getAutofill(browser.getKey(), browser.getValue());
this.getAutofill(browser.getKey(), browser.getValue(), ingestJobId);
if (context.dataSourceIngestIsCancelled()) {
return;
}
progressBar.progress(NbBundle.getMessage(this.getClass(), "Progress_Message_Chrome_Downloads", browserName));
this.getDownload(browser.getKey(), browser.getValue());
this.getDownload(browser.getKey(), browser.getValue(), ingestJobId);
if (context.dataSourceIngestIsCancelled()) {
return;
}
@ -179,8 +180,11 @@ class Chromium extends Extract {
/**
* Query for history databases and add artifacts
* @param browser
* @param browserLocation
* @param ingestJobId The ingest job id.
*/
private void getHistory(String browser, String browserLocation) {
private void getHistory(String browser, String browserLocation, long ingestJobId) {
FileManager fileManager = currentCase.getServices().getFileManager();
List<AbstractFile> historyFiles;
String historyFileName = HISTORY_FILE_NAME;
@ -215,7 +219,7 @@ class Chromium extends Extract {
Collection<BlackboardArtifact> bbartifacts = new ArrayList<>();
int j = 0;
while (j < allocatedHistoryFiles.size()) {
String temps = RAImageIngestModule.getRATempPath(currentCase, browser) + File.separator + allocatedHistoryFiles.get(j).getName() + j + ".db"; //NON-NLS
String temps = RAImageIngestModule.getRATempPath(currentCase, browser, ingestJobId) + File.separator + allocatedHistoryFiles.get(j).getName() + j + ".db"; //NON-NLS
final AbstractFile historyFile = allocatedHistoryFiles.get(j++);
if ((historyFile.getSize() == 0) || (historyFile.getName().toLowerCase().contains("-slack"))
|| (historyFile.getName().toLowerCase().contains("cache")) || (historyFile.getName().toLowerCase().contains("media"))
@ -281,8 +285,11 @@ class Chromium extends Extract {
/**
* Search for bookmark files and make artifacts.
* @param browser
* @param browserLocation
* @param ingestJobId The ingest job id.
*/
private void getBookmark(String browser, String browserLocation) {
private void getBookmark(String browser, String browserLocation, long ingestJobId) {
FileManager fileManager = currentCase.getServices().getFileManager();
List<AbstractFile> bookmarkFiles;
String bookmarkFileName = BOOKMARK_FILE_NAME;
@ -315,7 +322,7 @@ class Chromium extends Extract {
|| (bookmarkFile.getName().toLowerCase().contains("bak")) || (bookmarkFile.getParentPath().toLowerCase().contains("backup"))) {
continue;
}
String temps = RAImageIngestModule.getRATempPath(currentCase, browser) + File.separator + bookmarkFile.getName() + j + ".db"; //NON-NLS
String temps = RAImageIngestModule.getRATempPath(currentCase, browser, ingestJobId) + File.separator + bookmarkFile.getName() + j + ".db"; //NON-NLS
try {
ContentUtils.writeToFile(bookmarkFile, new File(temps), context::dataSourceIngestIsCancelled);
} catch (ReadContentInputStreamException ex) {
@ -423,8 +430,11 @@ class Chromium extends Extract {
/**
* Queries for cookie files and adds artifacts
* @param browser
* @param browserLocation
* @param ingestJobId The ingest job id.
*/
private void getCookie(String browser, String browserLocation) {
private void getCookie(String browser, String browserLocation, long ingestJobId) {
FileManager fileManager = currentCase.getServices().getFileManager();
List<AbstractFile> cookiesFiles;
@ -456,7 +466,7 @@ class Chromium extends Extract {
if ((cookiesFile.getSize() == 0) || (cookiesFile.getName().toLowerCase().contains("-slack"))) {
continue;
}
String temps = RAImageIngestModule.getRATempPath(currentCase, browser) + File.separator + cookiesFile.getName() + j + ".db"; //NON-NLS
String temps = RAImageIngestModule.getRATempPath(currentCase, browser, ingestJobId) + File.separator + cookiesFile.getName() + j + ".db"; //NON-NLS
try {
ContentUtils.writeToFile(cookiesFile, new File(temps), context::dataSourceIngestIsCancelled);
} catch (ReadContentInputStreamException ex) {
@ -519,8 +529,11 @@ class Chromium extends Extract {
/**
* Queries for download files and adds artifacts
* @param browser
* @param browserLocation
* @param ingestJobId The ingest job id.
*/
private void getDownload(String browser, String browserLocation) {
private void getDownload(String browser, String browserLocation, long ingestJobId) {
FileManager fileManager = currentCase.getServices().getFileManager();
List<AbstractFile> downloadFiles;
String historyFileName = HISTORY_FILE_NAME;
@ -551,7 +564,7 @@ class Chromium extends Extract {
continue;
}
String temps = RAImageIngestModule.getRATempPath(currentCase, browser) + File.separator + downloadFile.getName() + j + ".db"; //NON-NLS
String temps = RAImageIngestModule.getRATempPath(currentCase, browser, ingestJobId) + File.separator + downloadFile.getName() + j + ".db"; //NON-NLS
try {
ContentUtils.writeToFile(downloadFile, new File(temps), context::dataSourceIngestIsCancelled);
} catch (ReadContentInputStreamException ex) {
@ -633,8 +646,11 @@ class Chromium extends Extract {
/**
* Gets user logins from Login Data sqlite database
* @param browser
* @param browserLocation
* @param ingestJobId The ingest job id.
*/
private void getLogins(String browser, String browserLocation) {
private void getLogins(String browser, String browserLocation, long ingestJobId) {
FileManager fileManager = currentCase.getServices().getFileManager();
List<AbstractFile> loginDataFiles;
@ -665,7 +681,7 @@ class Chromium extends Extract {
if ((loginDataFile.getSize() == 0) || (loginDataFile.getName().toLowerCase().contains("-slack"))) {
continue;
}
String temps = RAImageIngestModule.getRATempPath(currentCase, browser) + File.separator + loginDataFile.getName() + j + ".db"; //NON-NLS
String temps = RAImageIngestModule.getRATempPath(currentCase, browser, ingestJobId) + File.separator + loginDataFile.getName() + j + ".db"; //NON-NLS
try {
ContentUtils.writeToFile(loginDataFile, new File(temps), context::dataSourceIngestIsCancelled);
} catch (ReadContentInputStreamException ex) {
@ -736,8 +752,11 @@ class Chromium extends Extract {
/**
* Gets and parses Autofill data from 'Web Data' database, and creates
* TSK_WEB_FORM_AUTOFILL, TSK_WEB_FORM_ADDRESS artifacts
* @param browser
* @param browserLocation
* @param ingestJobId The ingest job id.
*/
private void getAutofill(String browser, String browserLocation) {
private void getAutofill(String browser, String browserLocation, long ingestJobId) {
FileManager fileManager = currentCase.getServices().getFileManager();
List<AbstractFile> webDataFiles;
@ -768,7 +787,7 @@ class Chromium extends Extract {
if ((webDataFile.getSize() == 0) || (webDataFile.getName().toLowerCase().contains("-slack"))) {
continue;
}
String tempFilePath = RAImageIngestModule.getRATempPath(currentCase, browser) + File.separator + webDataFile.getName() + j + ".db"; //NON-NLS
String tempFilePath = RAImageIngestModule.getRATempPath(currentCase, browser, ingestJobId) + File.separator + webDataFile.getName() + j + ".db"; //NON-NLS
try {
ContentUtils.writeToFile(webDataFile, new File(tempFilePath), context::dataSourceIngestIsCancelled);
} catch (ReadContentInputStreamException ex) {

View File

@ -128,18 +128,33 @@ public class DefaultDomainCategorizer implements DomainCategorizer {
private Map<String, String> mapping = null;
@Override
public void initialize() throws DomainCategorizerException {
if (this.mapping == null) {
public synchronized void initialize() throws DomainCategorizerException {
if (isInitialized()) {
return;
}
try {
this.mapping = loadMapping();
} catch (IOException ex) {
throw new DomainCategorizerException("Unable to load domain type csv for domain category analysis", ex);
}
}
/**
* Returns true if this categorizer is properly initialized.
*
* @return True if this categorizer is properly initialized.
*/
private synchronized boolean isInitialized() {
return this.mapping != null;
}
@Override
public DomainCategory getCategory(String domain, String host) throws DomainCategorizerException {
public synchronized DomainCategory getCategory(String domain, String host) throws DomainCategorizerException {
if (!isInitialized()) {
initialize();
}
// use host; use domain as fallback if no host provided
String hostToUse = StringUtils.isBlank(host) ? domain : host;
@ -162,7 +177,7 @@ public class DefaultDomainCategorizer implements DomainCategorizer {
}
@Override
public void close() throws Exception {
public synchronized void close() throws Exception {
// clear out the mapping to release resources
mapping = null;
}

View File

@ -520,12 +520,13 @@ abstract class Extract {
*
* @param context
* @param file
* @param IngestJobId The ingest job id.
* @return Newly created copy of the AbstractFile
* @throws IOException
*/
protected File createTemporaryFile(IngestJobContext context, AbstractFile file) throws IOException{
protected File createTemporaryFile(IngestJobContext context, AbstractFile file, long ingestJobId) throws IOException{
Path tempFilePath = Paths.get(RAImageIngestModule.getRATempPath(
getCurrentCase(), getName()), file.getName() + file.getId() + file.getNameExtension());
getCurrentCase(), getName(), ingestJobId), file.getName() + file.getId() + file.getNameExtension());
java.io.File tempFile = tempFilePath.toFile();
try {

View File

@ -64,7 +64,6 @@ import org.sleuthkit.datamodel.TskCoreException;
final class ExtractEdge extends Extract {
private static final Logger LOG = Logger.getLogger(ExtractEdge.class.getName());
private final Path moduleTempResultPath;
private Content dataSource;
private IngestJobContext context;
private HashMap<String, ArrayList<String>> containersTable;
@ -125,9 +124,8 @@ final class ExtractEdge extends Extract {
/**
* Extract the bookmarks, cookies, downloads and history from Microsoft Edge
*/
ExtractEdge() throws NoCurrentCaseException {
ExtractEdge() {
super(Bundle.ExtractEdge_Module_Name());
moduleTempResultPath = Paths.get(RAImageIngestModule.getRATempPath(Case.getCurrentCaseThrows(), EDGE), EDGE_RESULT_FOLDER_NAME);
}
@Override
@ -137,6 +135,9 @@ final class ExtractEdge extends Extract {
@Override
void process(Content dataSource, IngestJobContext context, DataSourceIngestModuleProgress progressBar) {
String moduleTempDir = RAImageIngestModule.getRATempPath(getCurrentCase(), EDGE, context.getJobId());
String moduleTempResultDir = Paths.get(moduleTempDir, EDGE_RESULT_FOLDER_NAME).toString();
this.dataSource = dataSource;
this.context = context;
this.setFoundData(false);
@ -186,7 +187,7 @@ final class ExtractEdge extends Extract {
}
try {
this.processWebCacheDbFile(esedumper, webCacheFiles, progressBar);
this.processWebCacheDbFile(esedumper, webCacheFiles, progressBar, moduleTempDir, moduleTempResultDir);
} catch (IOException | TskCoreException ex) {
LOG.log(Level.SEVERE, "Error processing 'WebCacheV01.dat' files for Microsoft Edge", ex); // NON-NLS
this.addErrorMessage(Bundle.ExtractEdge_process_errMsg_webcacheFail());
@ -194,7 +195,7 @@ final class ExtractEdge extends Extract {
progressBar.progress(Bundle.Progress_Message_Edge_Bookmarks());
try {
this.processSpartanDbFile(esedumper, spartanFiles);
this.processSpartanDbFile(esedumper, spartanFiles, moduleTempDir, moduleTempResultDir);
} catch (IOException | TskCoreException ex) {
LOG.log(Level.SEVERE, "Error processing 'spartan.edb' files for Microsoft Edge", ex); // NON-NLS
this.addErrorMessage(Bundle.ExtractEdge_process_errMsg_spartanFail());
@ -207,10 +208,13 @@ final class ExtractEdge extends Extract {
*
* @param eseDumperPath Path to ESEDatabaseView.exe
* @param webCacheFiles List of case WebCacheV01.dat files
* @param moduleTempDir The temp directory for this module.
* @param moduleTempResultDir The temp results directory for this module.
* @throws IOException
* @throws TskCoreException
*/
void processWebCacheDbFile(String eseDumperPath, List<AbstractFile> webCacheFiles, DataSourceIngestModuleProgress progressBar) throws IOException, TskCoreException {
void processWebCacheDbFile(String eseDumperPath, List<AbstractFile> webCacheFiles, DataSourceIngestModuleProgress progressBar,
String moduleTempDir, String moduleTempResultDir) throws IOException, TskCoreException {
for (AbstractFile webCacheFile : webCacheFiles) {
@ -223,7 +227,7 @@ final class ExtractEdge extends Extract {
//Run the dumper
String tempWebCacheFileName = EDGE_WEBCACHE_PREFIX
+ Integer.toString((int) webCacheFile.getId()) + EDGE_WEBCACHE_EXT; //NON-NLS
File tempWebCacheFile = new File(RAImageIngestModule.getRATempPath(currentCase, EDGE), tempWebCacheFileName);
File tempWebCacheFile = new File(moduleTempDir, tempWebCacheFileName);
try {
ContentUtils.writeToFile(webCacheFile, tempWebCacheFile,
@ -232,7 +236,7 @@ final class ExtractEdge extends Extract {
throw new IOException("Error writingToFile: " + webCacheFile, ex); //NON-NLS
}
File resultsDir = new File(moduleTempResultPath.toAbsolutePath() + Integer.toString((int) webCacheFile.getId()));
File resultsDir = new File(moduleTempDir, Integer.toString((int) webCacheFile.getId()));
resultsDir.mkdirs();
try {
executeDumper(eseDumperPath, tempWebCacheFile.getAbsolutePath(),
@ -267,10 +271,13 @@ final class ExtractEdge extends Extract {
*
* @param eseDumperPath Path to ESEDatabaseViewer
* @param spartanFiles List of the case spartan.edb files
* @param moduleTempDir The temp directory for this module.
* @param moduleTempResultDir The temp results directory for this module.
* @throws IOException
* @throws TskCoreException
*/
void processSpartanDbFile(String eseDumperPath, List<AbstractFile> spartanFiles) throws IOException, TskCoreException {
void processSpartanDbFile(String eseDumperPath, List<AbstractFile> spartanFiles,
String moduleTempDir, String moduleTempResultDir) throws IOException, TskCoreException {
for (AbstractFile spartanFile : spartanFiles) {
@ -281,7 +288,7 @@ final class ExtractEdge extends Extract {
//Run the dumper
String tempSpartanFileName = EDGE_WEBCACHE_PREFIX
+ Integer.toString((int) spartanFile.getId()) + EDGE_WEBCACHE_EXT;
File tempSpartanFile = new File(RAImageIngestModule.getRATempPath(currentCase, EDGE), tempSpartanFileName);
File tempSpartanFile = new File(moduleTempDir, tempSpartanFileName);
try {
ContentUtils.writeToFile(spartanFile, tempSpartanFile,
@ -290,7 +297,7 @@ final class ExtractEdge extends Extract {
throw new IOException("Error writingToFile: " + spartanFile, ex); //NON-NLS
}
File resultsDir = new File(moduleTempResultPath.toAbsolutePath() + Integer.toString((int) spartanFile.getId()));
File resultsDir = new File(moduleTempResultDir, Integer.toString((int) spartanFile.getId()));
resultsDir.mkdirs();
try {
executeDumper(eseDumperPath, tempSpartanFile.getAbsolutePath(),

View File

@ -31,6 +31,7 @@ import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStreamReader;
import java.nio.file.Paths;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
@ -43,7 +44,6 @@ import java.util.stream.Collectors;
import org.openide.modules.InstalledFileLocator;
import org.openide.util.NbBundle.Messages;
import org.sleuthkit.autopsy.casemodule.Case;
import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException;
import org.sleuthkit.autopsy.casemodule.services.FileManager;
import org.sleuthkit.autopsy.datamodel.ContentUtils;
import org.sleuthkit.datamodel.BlackboardArtifact;
@ -67,7 +67,6 @@ import org.sleuthkit.datamodel.TskCoreException;
class ExtractIE extends Extract {
private static final Logger logger = Logger.getLogger(ExtractIE.class.getName());
private final String moduleTempResultsDir;
private String PASCO_LIB_PATH;
private final String JAVA_PATH;
private static final String RESOURCE_URL_PREFIX = "res://";
@ -84,14 +83,16 @@ class ExtractIE extends Extract {
"Progress_Message_IE_AutoFill=IE Auto Fill",
"Progress_Message_IE_Logins=IE Logins",})
ExtractIE() throws NoCurrentCaseException {
ExtractIE() {
super(NbBundle.getMessage(ExtractIE.class, "ExtractIE.moduleName.text"));
moduleTempResultsDir = RAImageIngestModule.getRATempPath(Case.getCurrentCaseThrows(), "IE") + File.separator + "results"; //NON-NLS
JAVA_PATH = PlatformUtil.getJavaPath();
}
@Override
public void process(Content dataSource, IngestJobContext context, DataSourceIngestModuleProgress progressBar) {
String moduleTempDir = RAImageIngestModule.getRATempPath(getCurrentCase(), "IE", context.getJobId());
String moduleTempResultsDir = Paths.get(moduleTempDir, "results").toString();
this.dataSource = dataSource;
this.context = context;
dataFound = false;
@ -111,7 +112,7 @@ class ExtractIE extends Extract {
}
progressBar.progress(Bundle.Progress_Message_IE_History());
this.getHistory();
this.getHistory(moduleTempDir, moduleTempResultsDir);
}
/**
@ -297,8 +298,10 @@ class ExtractIE extends Extract {
/**
* Locates index.dat files, runs Pasco on them, and creates artifacts.
* @param moduleTempDir The path to the module temp directory.
* @param moduleTempResultsDir The path to the module temp results directory.
*/
private void getHistory() {
private void getHistory(String moduleTempDir, String moduleTempResultsDir) {
logger.log(Level.INFO, "Pasco results path: {0}", moduleTempResultsDir); //NON-NLS
boolean foundHistory = false;
@ -350,7 +353,7 @@ class ExtractIE extends Extract {
//BlackboardArtifact bbart = fsc.newArtifact(ARTIFACT_TYPE.TSK_WEB_HISTORY);
indexFileName = "index" + Integer.toString((int) indexFile.getId()) + ".dat"; //NON-NLS
//indexFileName = "index" + Long.toString(bbart.getArtifactID()) + ".dat";
temps = RAImageIngestModule.getRATempPath(currentCase, "IE") + File.separator + indexFileName; //NON-NLS
temps = moduleTempDir + File.separator + indexFileName; //NON-NLS
File datFile = new File(temps);
if (context.dataSourceIngestIsCancelled()) {
break;
@ -366,7 +369,7 @@ class ExtractIE extends Extract {
}
String filename = "pasco2Result." + indexFile.getId() + ".txt"; //NON-NLS
boolean bPascProcSuccess = executePasco(temps, filename);
boolean bPascProcSuccess = executePasco(temps, filename, moduleTempResultsDir);
if (context.dataSourceIngestIsCancelled()) {
return;
}
@ -375,7 +378,7 @@ class ExtractIE extends Extract {
//Now fetch the results, parse them and the delete the files.
if (bPascProcSuccess) {
// Don't add TSK_OS_ACCOUNT artifacts to the ModuleDataEvent
bbartifacts.addAll(parsePascoOutput(indexFile, filename).stream()
bbartifacts.addAll(parsePascoOutput(indexFile, filename, moduleTempResultsDir).stream()
.filter(bbart -> bbart.getArtifactTypeID() == ARTIFACT_TYPE.TSK_WEB_HISTORY.getTypeID())
.collect(Collectors.toList()));
if (context.dataSourceIngestIsCancelled()) {
@ -402,6 +405,7 @@ class ExtractIE extends Extract {
*
* @param indexFilePath Path to local index.dat file to analyze
* @param outputFileName Name of file to save output to
* @param moduleTempResultsDir the path to the module temp directory.
*
* @return false on error
*/
@ -409,7 +413,7 @@ class ExtractIE extends Extract {
"# {0} - sub module name",
"ExtractIE_executePasco_errMsg_errorRunningPasco={0}: Error analyzing Internet Explorer web history",
})
private boolean executePasco(String indexFilePath, String outputFileName) {
private boolean executePasco(String indexFilePath, String outputFileName, String moduleTempResultsDir) {
boolean success = true;
try {
final String outputFileFullPath = moduleTempResultsDir + File.separator + outputFileName;
@ -451,10 +455,11 @@ class ExtractIE extends Extract {
* @param origFile Original index.dat file that was analyzed to
* get this output
* @param pascoOutputFileName name of pasco output file
* @param moduleTempResultsDir the path to the module temp directory.
*
* @return A collection of created artifacts
*/
private Collection<BlackboardArtifact> parsePascoOutput(AbstractFile origFile, String pascoOutputFileName) {
private Collection<BlackboardArtifact> parsePascoOutput(AbstractFile origFile, String pascoOutputFileName, String moduleTempResultsDir) {
Collection<BlackboardArtifact> bbartifacts = new ArrayList<>();
String fnAbs = moduleTempResultsDir + File.separator + pascoOutputFileName;

View File

@ -91,6 +91,7 @@ final class ExtractPrefetch extends Extract {
void process(Content dataSource, IngestJobContext context, DataSourceIngestModuleProgress progressBar) {
this.context = context;
long ingestJobId = context.getJobId();
String modOutPath = Case.getCurrentCase().getModuleDirectory() + File.separator + PREFETCH_DIR_NAME;
File dir = new File(modOutPath);
@ -102,7 +103,7 @@ final class ExtractPrefetch extends Extract {
}
}
extractPrefetchFiles(dataSource);
extractPrefetchFiles(dataSource, ingestJobId);
final String prefetchDumper = getPathForPrefetchDumper();
if (prefetchDumper == null) {
@ -116,7 +117,7 @@ final class ExtractPrefetch extends Extract {
String modOutFile = modOutPath + File.separator + dataSource.getName() + "-" + PREFETCH_PARSER_DB_FILE;
try {
String tempDirPath = RAImageIngestModule.getRATempPath(Case.getCurrentCase(), dataSource.getName() + "-" + PREFETCH_DIR_NAME);
String tempDirPath = RAImageIngestModule.getRATempPath(Case.getCurrentCase(), dataSource.getName() + "-" + PREFETCH_DIR_NAME, ingestJobId);
parsePrefetchFiles(prefetchDumper, tempDirPath, modOutFile, modOutPath);
createAppExecArtifacts(modOutFile, dataSource);
} catch (IOException ex) {
@ -131,7 +132,7 @@ final class ExtractPrefetch extends Extract {
*
* @param dataSource - datasource to search for prefetch files
*/
void extractPrefetchFiles(Content dataSource) {
void extractPrefetchFiles(Content dataSource, long ingestJobId) {
List<AbstractFile> pFiles;
FileManager fileManager = Case.getCurrentCase().getServices().getFileManager();
@ -154,7 +155,7 @@ final class ExtractPrefetch extends Extract {
String ext = FilenameUtils.getExtension(origFileName);
String baseName = FilenameUtils.getBaseName(origFileName);
String fileName = String.format("%s_%d.%s", baseName, pFile.getId(), ext);
String baseRaTempPath = RAImageIngestModule.getRATempPath(Case.getCurrentCase(), dataSource.getName() + "-" + PREFETCH_DIR_NAME);
String baseRaTempPath = RAImageIngestModule.getRATempPath(Case.getCurrentCase(), dataSource.getName() + "-" + PREFETCH_DIR_NAME, ingestJobId);
String prefetchFile = Paths.get(baseRaTempPath, fileName).toString();
try {
ContentUtils.writeToFile(pFile, new File(prefetchFile));

View File

@ -136,7 +136,7 @@ final class ExtractRecycleBin extends Extract {
return; // No need to continue
}
String tempRARecycleBinPath = RAImageIngestModule.getRATempPath(Case.getCurrentCase(), "recyclebin"); //NON-NLS
String tempRARecycleBinPath = RAImageIngestModule.getRATempPath(Case.getCurrentCase(), "recyclebin", context.getJobId()); //NON-NLS
// cycle through the $I files and process each.
for (AbstractFile iFile : iFiles) {

View File

@ -294,14 +294,15 @@ class ExtractRegistry extends Extract {
/**
* Identifies registry files in the database by mtimeItem, runs regripper on
* them, and parses the output.
* @param ingestJobId The ingest job id.
*/
private void analyzeRegistryFiles() {
private void analyzeRegistryFiles(long ingestJobId) {
List<AbstractFile> allRegistryFiles = findRegistryFiles();
// open the log file
FileWriter logFile = null;
try {
logFile = new FileWriter(RAImageIngestModule.getRAOutputPath(currentCase, "reg") + File.separator + "regripper-info.txt"); //NON-NLS
logFile = new FileWriter(RAImageIngestModule.getRAOutputPath(currentCase, "reg", ingestJobId) + File.separator + "regripper-info.txt"); //NON-NLS
} catch (IOException ex) {
logger.log(Level.SEVERE, null, ex);
}
@ -313,8 +314,8 @@ class ExtractRegistry extends Extract {
String regFileName = regFile.getName();
long regFileId = regFile.getId();
String regFileNameLocal = RAImageIngestModule.getRATempPath(currentCase, "reg") + File.separator + regFileName;
String outputPathBase = RAImageIngestModule.getRAOutputPath(currentCase, "reg") + File.separator + regFileName + "-regripper-" + Long.toString(regFileId); //NON-NLS
String regFileNameLocal = RAImageIngestModule.getRATempPath(currentCase, "reg", ingestJobId) + File.separator + regFileName;
String outputPathBase = RAImageIngestModule.getRAOutputPath(currentCase, "reg", ingestJobId) + File.separator + regFileName + "-regripper-" + Long.toString(regFileId); //NON-NLS
File regFileNameLocalFile = new File(regFileNameLocal);
try {
ContentUtils.writeToFile(regFile, regFileNameLocalFile, context::dataSourceIngestIsCancelled);
@ -366,7 +367,7 @@ class ExtractRegistry extends Extract {
// create a report for the full output
if (!regOutputFiles.fullPlugins.isEmpty()) {
//parse the full regripper output from SAM hive files
if (regFileNameLocal.toLowerCase().contains("sam") && parseSamPluginOutput(regOutputFiles.fullPlugins, regFile) == false) {
if (regFileNameLocal.toLowerCase().contains("sam") && parseSamPluginOutput(regOutputFiles.fullPlugins, regFile, ingestJobId) == false) {
this.addErrorMessage(
NbBundle.getMessage(this.getClass(), "ExtractRegistry.analyzeRegFiles.failedParsingResults",
this.getName(), regFileName));
@ -1049,11 +1050,12 @@ class ExtractRegistry extends Extract {
*
* @param regFilePath the path to the registry file being parsed
* @param regAbstractFile the file to associate newly created artifacts with
* @param ingestJobId The ingest job id.
*
* @return true if successful, false if parsing failed at some point
*/
private boolean parseSamPluginOutput(String regFilePath, AbstractFile regAbstractFile) {
parseSystemHostDomain();
private boolean parseSamPluginOutput(String regFilePath, AbstractFile regAbstractFile, long ingestJobId) {
parseSystemHostDomain(ingestJobId);
File regfile = new File(regFilePath);
List<BlackboardArtifact> newArtifacts = new ArrayList<>();
@ -1139,14 +1141,15 @@ class ExtractRegistry extends Extract {
/**
* Finds the Host and Domain information from the registry.
* @param ingestJobId The ingest job id.
*/
private void parseSystemHostDomain() {
private void parseSystemHostDomain(long ingestJobId) {
List<AbstractFile> regFiles = findRegistryFiles();
for (AbstractFile systemHive: regFiles) {
if (systemHive.getName().toLowerCase().equals("system")) {
String systemFileNameLocal = RAImageIngestModule.getRATempPath(currentCase, "reg") + File.separator + systemHive.getName();
String systemFileNameLocal = RAImageIngestModule.getRATempPath(currentCase, "reg", ingestJobId) + File.separator + systemHive.getName();
File systemFileNameLocalFile = new File(systemFileNameLocal);
if (!systemFileNameLocalFile.exists()) {
@ -1989,7 +1992,7 @@ class ExtractRegistry extends Extract {
this.context = context;
progressBar.progress(Bundle.Progress_Message_Analyze_Registry());
analyzeRegistryFiles();
analyzeRegistryFiles(context.getJobId());
}

View File

@ -289,7 +289,7 @@ final class ExtractSafari extends Extract {
return;
}
File tempHistoryFile = createTemporaryFile(context, historyFile);
File tempHistoryFile = createTemporaryFile(context, historyFile, context.getJobId());
try {
ContentUtils.writeToFile(historyFile, tempHistoryFile, context::dataSourceIngestIsCancelled);
@ -324,7 +324,7 @@ final class ExtractSafari extends Extract {
return;
}
File tempFile = createTemporaryFile(context, file);
File tempFile = createTemporaryFile(context, file, context.getJobId());
try {
if(!context.dataSourceIngestIsCancelled()) {
@ -354,7 +354,7 @@ final class ExtractSafari extends Extract {
return;
}
File tempFile = createTemporaryFile(context, file);
File tempFile = createTemporaryFile(context, file, context.getJobId());
try {
if(!context.dataSourceIngestIsCancelled()) {
@ -385,7 +385,7 @@ final class ExtractSafari extends Extract {
File tempFile = null;
try {
tempFile = createTemporaryFile(context, file);
tempFile = createTemporaryFile(context, file, context.getJobId());
if(!context.dataSourceIngestIsCancelled()) {
postArtifacts(getCookieArtifacts(file, tempFile, context));

View File

@ -100,7 +100,7 @@ final class ExtractSru extends Extract {
dir.mkdirs();
}
String tempDirPath = RAImageIngestModule.getRATempPath(Case.getCurrentCase(), "sru"); //NON-NLS
String tempDirPath = RAImageIngestModule.getRATempPath(Case.getCurrentCase(), "sru", context.getJobId()); //NON-NLS
String softwareHiveFileName = getSoftwareHiveFile(dataSource, tempDirPath);
if (softwareHiveFileName == null) {

View File

@ -108,47 +108,52 @@ class Firefox extends Extract {
this.dataSource = dataSource;
this.context = context;
dataFound = false;
long ingestJobId = context.getJobId();
progressBar.progress(Bundle.Progress_Message_Firefox_History());
this.getHistory();
this.getHistory(context.getJobId());
if (context.dataSourceIngestIsCancelled()) {
return;
}
progressBar.progress(Bundle.Progress_Message_Firefox_Bookmarks());
this.getBookmark();
this.getBookmark(ingestJobId);
if (context.dataSourceIngestIsCancelled()) {
return;
}
progressBar.progress(Bundle.Progress_Message_Firefox_Downloads());
this.getDownload();
this.getDownload(ingestJobId);
if (context.dataSourceIngestIsCancelled()) {
return;
}
progressBar.progress(Bundle.Progress_Message_Firefox_Cookies());
this.getCookie();
this.getCookie(ingestJobId);
if (context.dataSourceIngestIsCancelled()) {
return;
}
progressBar.progress(Bundle.Progress_Message_Firefox_FormHistory());
this.getFormsHistory();
this.getFormsHistory(ingestJobId);
if (context.dataSourceIngestIsCancelled()) {
return;
}
progressBar.progress(Bundle.Progress_Message_Firefox_AutoFill());
this.getAutofillProfiles();
this.getAutofillProfiles(ingestJobId);
}
private void getHistory() {
/**
* Get Firefox history.
* @param ingestJobId The ingest job id.
*/
private void getHistory(long ingestJobId) {
FileManager fileManager = currentCase.getServices().getFileManager();
List<AbstractFile> historyFiles;
try {
@ -180,7 +185,7 @@ class Firefox extends Extract {
}
String fileName = historyFile.getName();
String temps = RAImageIngestModule.getRATempPath(currentCase, "firefox") + File.separator + fileName + j + ".db"; //NON-NLS
String temps = RAImageIngestModule.getRATempPath(currentCase, "firefox", ingestJobId) + File.separator + fileName + j + ".db"; //NON-NLS
try {
ContentUtils.writeToFile(historyFile, new File(temps), context::dataSourceIngestIsCancelled);
} catch (ReadContentInputStreamException ex) {
@ -254,8 +259,9 @@ class Firefox extends Extract {
/**
* Queries for bookmark files and adds artifacts
* @param ingestJobId The ingest job id.
*/
private void getBookmark() {
private void getBookmark(long ingestJobId) {
FileManager fileManager = currentCase.getServices().getFileManager();
List<AbstractFile> bookmarkFiles;
@ -281,7 +287,7 @@ class Firefox extends Extract {
continue;
}
String fileName = bookmarkFile.getName();
String temps = RAImageIngestModule.getRATempPath(currentCase, "firefox") + File.separator + fileName + j + ".db"; //NON-NLS
String temps = RAImageIngestModule.getRATempPath(currentCase, "firefox", ingestJobId) + File.separator + fileName + j + ".db"; //NON-NLS
try {
ContentUtils.writeToFile(bookmarkFile, new File(temps), context::dataSourceIngestIsCancelled);
} catch (ReadContentInputStreamException ex) {
@ -351,8 +357,9 @@ class Firefox extends Extract {
/**
* Queries for cookies file and adds artifacts
* @param ingestJobId The ingest job id.
*/
private void getCookie() {
private void getCookie(long ingestJobId) {
FileManager fileManager = currentCase.getServices().getFileManager();
List<AbstractFile> cookiesFiles;
try {
@ -381,7 +388,7 @@ class Firefox extends Extract {
continue;
}
String fileName = cookiesFile.getName();
String temps = RAImageIngestModule.getRATempPath(currentCase, "firefox") + File.separator + fileName + j + ".db"; //NON-NLS
String temps = RAImageIngestModule.getRATempPath(currentCase, "firefox", ingestJobId) + File.separator + fileName + j + ".db"; //NON-NLS
try {
ContentUtils.writeToFile(cookiesFile, new File(temps), context::dataSourceIngestIsCancelled);
} catch (ReadContentInputStreamException ex) {
@ -468,18 +475,20 @@ class Firefox extends Extract {
/**
* Queries for downloads files and adds artifacts
* @param ingestJobId The ingest job id.
*/
private void getDownload() {
getDownloadPreVersion24();
getDownloadVersion24();
private void getDownload(long ingestJobId) {
getDownloadPreVersion24(ingestJobId);
getDownloadVersion24(ingestJobId);
}
/**
* Finds downloads artifacts from Firefox data from versions before 24.0.
*
* Downloads were stored in a separate downloads database.
* @param ingestJobId The ingest job id.
*/
private void getDownloadPreVersion24() {
private void getDownloadPreVersion24(long ingestJobId) {
FileManager fileManager = currentCase.getServices().getFileManager();
List<AbstractFile> downloadsFiles;
@ -505,7 +514,7 @@ class Firefox extends Extract {
continue;
}
String fileName = downloadsFile.getName();
String temps = RAImageIngestModule.getRATempPath(currentCase, "firefox") + File.separator + fileName + j + ".db"; //NON-NLS
String temps = RAImageIngestModule.getRATempPath(currentCase, "firefox", ingestJobId) + File.separator + fileName + j + ".db"; //NON-NLS
int errors = 0;
try {
ContentUtils.writeToFile(downloadsFile, new File(temps), context::dataSourceIngestIsCancelled);
@ -611,8 +620,9 @@ class Firefox extends Extract {
* Gets download artifacts from Firefox data from version 24.
*
* Downloads are stored in the places database.
* @param ingestJobId The ingest job id.
*/
private void getDownloadVersion24() {
private void getDownloadVersion24(long ingestJobId) {
FileManager fileManager = currentCase.getServices().getFileManager();
List<AbstractFile> downloadsFiles;
try {
@ -637,7 +647,7 @@ class Firefox extends Extract {
continue;
}
String fileName = downloadsFile.getName();
String temps = RAImageIngestModule.getRATempPath(currentCase, "firefox") + File.separator + fileName + "-downloads" + j + ".db"; //NON-NLS
String temps = RAImageIngestModule.getRATempPath(currentCase, "firefox", ingestJobId) + File.separator + fileName + "-downloads" + j + ".db"; //NON-NLS
int errors = 0;
try {
ContentUtils.writeToFile(downloadsFile, new File(temps), context::dataSourceIngestIsCancelled);
@ -742,8 +752,9 @@ class Firefox extends Extract {
/**
* Gets data from formshistory.sqlite database.
* Parses and creates artifacts.
* @param ingestJobId The ingest job id.
*/
private void getFormsHistory() {
private void getFormsHistory(long ingestJobId) {
FileManager fileManager = currentCase.getServices().getFileManager();
List<AbstractFile> formHistoryFiles;
@ -777,7 +788,7 @@ class Firefox extends Extract {
}
String fileName = formHistoryFile.getName();
String tempFilePath = RAImageIngestModule.getRATempPath(currentCase, "firefox") + File.separator + fileName + j + ".db"; //NON-NLS
String tempFilePath = RAImageIngestModule.getRATempPath(currentCase, "firefox", ingestJobId) + File.separator + fileName + j + ".db"; //NON-NLS
try {
ContentUtils.writeToFile(formHistoryFile, new File(tempFilePath), context::dataSourceIngestIsCancelled);
} catch (ReadContentInputStreamException ex) {
@ -864,9 +875,9 @@ class Firefox extends Extract {
/**
* Gets data from autofill-profiles.json file.
* Parses file and makes artifacts.
*
* @param ingestJobId The ingest job id.
*/
private void getAutofillProfiles() {
private void getAutofillProfiles(long ingestJobId) {
FileManager fileManager = currentCase.getServices().getFileManager();
List<AbstractFile> autofillProfilesFiles;
try {
@ -891,7 +902,7 @@ class Firefox extends Extract {
if (profileFile.getSize() == 0) {
continue;
}
String temps = RAImageIngestModule.getRATempPath(currentCase, "Firefox") + File.separator + profileFile.getName() + j + ".json"; //NON-NLS
String temps = RAImageIngestModule.getRATempPath(currentCase, "Firefox", ingestJobId) + File.separator + profileFile.getName() + j + ".json"; //NON-NLS
try {
ContentUtils.writeToFile(profileFile, new File(temps), context::dataSourceIngestIsCancelled);
} catch (ReadContentInputStreamException ex) {

View File

@ -23,15 +23,16 @@
package org.sleuthkit.autopsy.recentactivity;
import java.io.File;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.logging.Level;
import org.openide.util.NbBundle;
import org.sleuthkit.autopsy.casemodule.Case;
import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException;
import org.sleuthkit.autopsy.coreutils.Logger;
import org.sleuthkit.autopsy.coreutils.TimeStampUtils;
import org.sleuthkit.autopsy.ingest.DataSourceIngestModule;
import org.sleuthkit.autopsy.ingest.DataSourceIngestModuleProgress;
import org.sleuthkit.autopsy.ingest.IngestServices;
@ -41,7 +42,6 @@ import org.sleuthkit.datamodel.Content;
import org.sleuthkit.autopsy.ingest.IngestModule.ProcessResult;
import org.sleuthkit.autopsy.ingest.IngestJobContext;
import org.sleuthkit.datamodel.DataSource;
import org.sleuthkit.datamodel.OsAccount;
import org.sleuthkit.datamodel.SleuthkitCase;
/**
@ -49,6 +49,7 @@ import org.sleuthkit.datamodel.SleuthkitCase;
*/
public final class RAImageIngestModule implements DataSourceIngestModule {
private static final String RECENT_ACTIVITY_FOLDER = "RecentActivity";
private static final Logger logger = Logger.getLogger(RAImageIngestModule.class.getName());
private final List<Extract> extractors = new ArrayList<>();
private final List<Extract> browserExtractors = new ArrayList<>();
@ -67,15 +68,8 @@ public final class RAImageIngestModule implements DataSourceIngestModule {
tskCase = Case.getCurrentCase().getSleuthkitCase();
Extract iexplore;
Extract edge;
try {
iexplore = new ExtractIE();
edge = new ExtractEdge();
} catch (NoCurrentCaseException ex) {
throw new IngestModuleException(ex.getMessage(), ex);
}
Extract iexplore = new ExtractIE();
Extract edge = new ExtractEdge();
Extract registry = new ExtractRegistry();
Extract recentDocuments = new RecentDocumentsByLnk();
Extract chrome = new Chromium();
@ -221,6 +215,27 @@ public final class RAImageIngestModule implements DataSourceIngestModule {
return ProcessResult.OK;
}
/**
* Makes a path of the format
* [basePath]/[RECENT_ACTIVITY_FOLDER]/[module]_[ingest job id] if it does not
* already exist and returns the created folder.
*
* @param basePath The base path (a case-related folder like temp or
* output).
* @param module The module name to include in the folder name.
* @param ingestJobId The id of the ingest job.
* @return The path to the folder.
*/
private static String getAndMakeRAPath(String basePath, String module, long ingestJobId) {
String moduleFolder = String.format("%s_%d", module, ingestJobId);
Path tmpPath = Paths.get(basePath, RECENT_ACTIVITY_FOLDER, moduleFolder);
File dir = tmpPath.toFile();
if (dir.exists() == false) {
dir.mkdirs();
}
return tmpPath.toString();
}
/**
* Get the temp path for a specific sub-module in recent activity. Will
* create the dir if it doesn't exist.
@ -231,13 +246,8 @@ public final class RAImageIngestModule implements DataSourceIngestModule {
*
* @return Path to directory
*/
static String getRATempPath(Case a_case, String mod) {
String tmpDir = a_case.getTempDirectory() + File.separator + "RecentActivity" + File.separator + mod; //NON-NLS
File dir = new File(tmpDir);
if (dir.exists() == false) {
dir.mkdirs();
}
return tmpDir;
static String getRATempPath(Case a_case, String mod, long ingestJobId) {
return getAndMakeRAPath(a_case.getTempDirectory(), mod, ingestJobId);
}
/**
@ -250,13 +260,8 @@ public final class RAImageIngestModule implements DataSourceIngestModule {
*
* @return Path to directory
*/
static String getRAOutputPath(Case a_case, String mod) {
String tmpDir = a_case.getModuleDirectory() + File.separator + "RecentActivity" + File.separator + mod; //NON-NLS
File dir = new File(tmpDir);
if (dir.exists() == false) {
dir.mkdirs();
}
return tmpDir;
static String getRAOutputPath(Case a_case, String mod, long ingestJobId) {
return getAndMakeRAPath(a_case.getModuleDirectory(), mod, ingestJobId);
}
/**
@ -265,8 +270,9 @@ public final class RAImageIngestModule implements DataSourceIngestModule {
* @throws NoCurrentCaseException if there is no open case.
* @return the relative path of the module output folder
*/
static String getRelModuleOutputPath() throws NoCurrentCaseException {
return Paths.get(Case.getCurrentCaseThrows().getModuleOutputDirectoryRelativePath(),
"RecentActivity").normalize().toString() ; //NON-NLS
static String getRelModuleOutputPath(Case autCase, String mod, long ingestJobId) {
return Paths.get(getAndMakeRAPath(autCase.getModuleOutputDirectoryRelativePath(), mod, ingestJobId))
.normalize()
.toString();
}
}