mirror of
https://github.com/overcuriousity/autopsy-flatpak.git
synced 2025-07-06 21:00:22 +00:00
Merge pull request #4914 from kellykelly3/1268-dynamic-account-types
1268 dynamic account types
This commit is contained in:
commit
a70a910fab
@ -66,7 +66,7 @@
|
||||
</Properties>
|
||||
<Constraints>
|
||||
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
|
||||
<GridBagConstraints gridX="1" gridY="0" gridWidth="1" gridHeight="1" fill="0" ipadX="0" ipadY="0" insetsTop="0" insetsLeft="0" insetsBottom="0" insetsRight="0" anchor="12" weightX="0.0" weightY="0.0"/>
|
||||
<GridBagConstraints gridX="1" gridY="0" gridWidth="1" gridHeight="1" fill="0" ipadX="0" ipadY="0" insetsTop="0" insetsLeft="0" insetsBottom="0" insetsRight="5" anchor="12" weightX="0.0" weightY="0.0"/>
|
||||
</Constraint>
|
||||
</Constraints>
|
||||
</Component>
|
||||
@ -95,7 +95,7 @@
|
||||
</Properties>
|
||||
<Constraints>
|
||||
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
|
||||
<GridBagConstraints gridX="0" gridY="1" gridWidth="1" gridHeight="1" fill="1" ipadX="0" ipadY="0" insetsTop="0" insetsLeft="0" insetsBottom="0" insetsRight="0" anchor="18" weightX="1.0" weightY="1.0"/>
|
||||
<GridBagConstraints gridX="0" gridY="1" gridWidth="1" gridHeight="1" fill="1" ipadX="0" ipadY="0" insetsTop="9" insetsLeft="0" insetsBottom="0" insetsRight="0" anchor="18" weightX="1.0" weightY="1.0"/>
|
||||
</Constraint>
|
||||
</Constraints>
|
||||
|
||||
@ -464,7 +464,7 @@
|
||||
<Container class="javax.swing.JPanel" name="accountTypeListPane">
|
||||
|
||||
<Layout class="org.netbeans.modules.form.compat2.layouts.DesignBoxLayout">
|
||||
<Property name="axis" type="int" value="1"/>
|
||||
<Property name="axis" type="int" value="3"/>
|
||||
</Layout>
|
||||
</Container>
|
||||
</SubComponents>
|
||||
|
@ -53,6 +53,7 @@ import org.sleuthkit.autopsy.core.UserPreferences;
|
||||
import org.sleuthkit.autopsy.coreutils.Logger;
|
||||
import org.sleuthkit.autopsy.coreutils.ThreadConfined;
|
||||
import org.sleuthkit.autopsy.ingest.IngestManager;
|
||||
import static org.sleuthkit.autopsy.ingest.IngestManager.IngestJobEvent.COMPLETED;
|
||||
import static org.sleuthkit.autopsy.ingest.IngestManager.IngestModuleEvent.DATA_ADDED;
|
||||
import org.sleuthkit.autopsy.ingest.ModuleDataEvent;
|
||||
import org.sleuthkit.datamodel.Account;
|
||||
@ -63,6 +64,7 @@ import org.sleuthkit.datamodel.CommunicationsFilter.AccountTypeFilter;
|
||||
import org.sleuthkit.datamodel.CommunicationsFilter.DateRangeFilter;
|
||||
import org.sleuthkit.datamodel.CommunicationsFilter.DeviceFilter;
|
||||
import org.sleuthkit.datamodel.CommunicationsFilter.MostRecentFilter;
|
||||
import org.sleuthkit.datamodel.CommunicationsManager;
|
||||
import org.sleuthkit.datamodel.DataSource;
|
||||
import static org.sleuthkit.datamodel.Relationship.Type.CALL_LOG;
|
||||
import static org.sleuthkit.datamodel.Relationship.Type.CONTACT;
|
||||
@ -96,9 +98,10 @@ final public class FiltersPanel extends JPanel {
|
||||
* Listens to ingest events to enable refresh button
|
||||
*/
|
||||
private final PropertyChangeListener ingestListener;
|
||||
private final PropertyChangeListener ingestJobListener;
|
||||
|
||||
/**
|
||||
* Flag that indicates the UI is not up-sto-date with respect to the case DB
|
||||
* Flag that indicates the UI is not up-to-date with respect to the case DB
|
||||
* and it should be refreshed (by reapplying the filters).
|
||||
*/
|
||||
private boolean needsRefresh;
|
||||
@ -123,6 +126,11 @@ final public class FiltersPanel extends JPanel {
|
||||
@NbBundle.Messages({"refreshText=Refresh Results", "applyText=Apply"})
|
||||
public FiltersPanel() {
|
||||
initComponents();
|
||||
|
||||
CheckBoxIconPanel panel = createAccoutTypeCheckBoxPanel(Account.Type.DEVICE, true);
|
||||
accountTypeMap.put(Account.Type.DEVICE, panel.getCheckBox());
|
||||
accountTypeListPane.add(panel);
|
||||
|
||||
deviceRequiredLabel.setVisible(false);
|
||||
accountTypeRequiredLabel.setVisible(false);
|
||||
startDatePicker.setDate(LocalDate.now().minusWeeks(3));
|
||||
@ -155,18 +163,30 @@ final public class FiltersPanel extends JPanel {
|
||||
// Indicate that a refresh may be needed, unless the data added is Keyword or Hashset hits
|
||||
ModuleDataEvent eventData = (ModuleDataEvent) pce.getOldValue();
|
||||
if (null != eventData
|
||||
&& eventData.getBlackboardArtifactType().getTypeID() != BlackboardArtifact.ARTIFACT_TYPE.TSK_KEYWORD_HIT.getTypeID()
|
||||
&& eventData.getBlackboardArtifactType().getTypeID() != BlackboardArtifact.ARTIFACT_TYPE.TSK_HASHSET_HIT.getTypeID()) {
|
||||
updateFilters(false);
|
||||
&& (eventData.getBlackboardArtifactType().getTypeID() == BlackboardArtifact.ARTIFACT_TYPE.TSK_MESSAGE.getTypeID()
|
||||
|| eventData.getBlackboardArtifactType().getTypeID() == BlackboardArtifact.ARTIFACT_TYPE.TSK_CONTACT.getTypeID()
|
||||
|| eventData.getBlackboardArtifactType().getTypeID() == BlackboardArtifact.ARTIFACT_TYPE.TSK_CALLLOG.getTypeID()
|
||||
|| eventData.getBlackboardArtifactType().getTypeID() == BlackboardArtifact.ARTIFACT_TYPE.TSK_EMAIL_MSG.getTypeID()))
|
||||
{
|
||||
updateFilters(true);
|
||||
needsRefresh = true;
|
||||
validateFilters();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
this.ingestJobListener = pce -> {
|
||||
String eventType = pce.getPropertyName();
|
||||
if (eventType.equals(COMPLETED.toString()) &&
|
||||
updateFilters(true)) {
|
||||
|
||||
needsRefresh = true;
|
||||
validateFilters();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
applyFiltersButton.addActionListener(e -> applyFilters());
|
||||
refreshButton.addActionListener(e -> applyFilters());
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
@ -219,19 +239,26 @@ final public class FiltersPanel extends JPanel {
|
||||
/**
|
||||
* Updates the filter widgets to reflect he data sources/types in the case.
|
||||
*/
|
||||
private void updateFilters(boolean initialState) {
|
||||
updateAccountTypeFilter();
|
||||
updateDeviceFilter(initialState);
|
||||
private boolean updateFilters(boolean initialState) {
|
||||
boolean newAccountType = updateAccountTypeFilter(initialState);
|
||||
boolean newDeviceFilter = updateDeviceFilter(initialState);
|
||||
|
||||
// both or either are true, return true;
|
||||
return newAccountType || newDeviceFilter;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addNotify() {
|
||||
super.addNotify();
|
||||
IngestManager.getInstance().addIngestModuleEventListener(ingestListener);
|
||||
IngestManager.getInstance().addIngestJobEventListener(ingestJobListener);
|
||||
Case.addEventTypeSubscriber(EnumSet.of(CURRENT_CASE), evt -> {
|
||||
//clear the device filter widget when the case changes.
|
||||
devicesMap.clear();
|
||||
devicesListPane.removeAll();
|
||||
|
||||
accountTypeMap.clear();
|
||||
accountTypeListPane.removeAll();
|
||||
});
|
||||
}
|
||||
|
||||
@ -239,64 +266,107 @@ final public class FiltersPanel extends JPanel {
|
||||
public void removeNotify() {
|
||||
super.removeNotify();
|
||||
IngestManager.getInstance().removeIngestModuleEventListener(ingestListener);
|
||||
IngestManager.getInstance().removeIngestJobEventListener(ingestJobListener);
|
||||
}
|
||||
|
||||
/**
|
||||
* Populate the Account Types filter widgets
|
||||
*
|
||||
* @param selected the initial value for the account type checkbox
|
||||
*
|
||||
* @return True, if a new accountType was found
|
||||
*/
|
||||
private void updateAccountTypeFilter() {
|
||||
|
||||
//TODO: something like this commented code could be used to show only
|
||||
//the account types that are found:
|
||||
//final CommunicationsManager communicationsManager = Case.getCurrentOpenCase().getSleuthkitCase().getCommunicationsManager();
|
||||
//List<Account.Type> accountTypesInUse = communicationsManager.getAccountTypesInUse();
|
||||
//accountTypesInUSe.forEach(...)
|
||||
Account.Type.PREDEFINED_ACCOUNT_TYPES.forEach(type -> {
|
||||
if (type.equals(Account.Type.CREDIT_CARD)) {
|
||||
//don't show a check box for credit cards
|
||||
} else {
|
||||
accountTypeMap.computeIfAbsent(type, t -> {
|
||||
|
||||
CheckBoxIconPanel panel = new CheckBoxIconPanel(
|
||||
type.getDisplayName(),
|
||||
new ImageIcon(FiltersPanel.class.getResource(Utils.getIconFilePath(type))));
|
||||
panel.setSelected(true);
|
||||
panel.addItemListener(validationListener);
|
||||
private boolean updateAccountTypeFilter(boolean selected) {
|
||||
boolean newOneFound = false;
|
||||
try {
|
||||
final CommunicationsManager communicationsManager = Case.getCurrentCaseThrows().getSleuthkitCase().getCommunicationsManager();
|
||||
List<Account.Type> accountTypesInUse = communicationsManager.getAccountTypesInUse();
|
||||
|
||||
for (Account.Type type : accountTypesInUse) {
|
||||
|
||||
if (!accountTypeMap.containsKey(type) && !type.equals(Account.Type.CREDIT_CARD)) {
|
||||
CheckBoxIconPanel panel = createAccoutTypeCheckBoxPanel(type, selected);
|
||||
accountTypeMap.put(type, panel.getCheckBox());
|
||||
accountTypeListPane.add(panel);
|
||||
if (t.equals(Account.Type.DEVICE)) {
|
||||
//Deveice type filter is enabled based on whether we are in table or graph view.
|
||||
panel.setEnabled(deviceAccountTypeEnabled);
|
||||
}
|
||||
return panel.getCheckBox();
|
||||
});
|
||||
|
||||
newOneFound = true;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
} catch (TskCoreException ex) {
|
||||
logger.log(Level.WARNING, "Unable to update to update Account Types Filter", ex);
|
||||
} catch (NoCurrentCaseException ex) {
|
||||
logger.log(Level.WARNING, "A case is required to update the account types filter.", ex);
|
||||
}
|
||||
|
||||
if (newOneFound) {
|
||||
accountTypeListPane.revalidate();
|
||||
}
|
||||
|
||||
return newOneFound;
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper function to create a new instance of the CheckBoxIconPanel base on
|
||||
* the Account.Type and initalState (check box state).
|
||||
*
|
||||
* @param type Account.Type to display on the panel
|
||||
* @param initalState initial check box state
|
||||
*
|
||||
* @return instance of the CheckBoxIconPanel
|
||||
*/
|
||||
private CheckBoxIconPanel createAccoutTypeCheckBoxPanel(Account.Type type, boolean initalState) {
|
||||
CheckBoxIconPanel panel = new CheckBoxIconPanel(
|
||||
type.getDisplayName(),
|
||||
new ImageIcon(FiltersPanel.class.getResource(Utils.getIconFilePath(type))));
|
||||
|
||||
panel.setSelected(initalState);
|
||||
panel.addItemListener(validationListener);
|
||||
if (type.equals(Account.Type.DEVICE)) {
|
||||
//Deveice type filter is enabled based on whether we are in table or graph view.
|
||||
panel.setEnabled(deviceAccountTypeEnabled);
|
||||
}
|
||||
|
||||
return panel;
|
||||
}
|
||||
|
||||
/**
|
||||
* Populate the devices filter widgets
|
||||
*
|
||||
* @param initialState
|
||||
* @param selected Sets the initial state of device check box
|
||||
*
|
||||
* @return true if a new device was found
|
||||
*/
|
||||
private void updateDeviceFilter(boolean initialState) {
|
||||
private boolean updateDeviceFilter(boolean selected) {
|
||||
boolean newOneFound = false;
|
||||
try {
|
||||
final SleuthkitCase sleuthkitCase = Case.getCurrentCaseThrows().getSleuthkitCase();
|
||||
|
||||
for (DataSource dataSource : sleuthkitCase.getDataSources()) {
|
||||
String dsName = sleuthkitCase.getContentById(dataSource.getId()).getName();
|
||||
//store the device id in the map, but display a datasource name in the UI.
|
||||
devicesMap.computeIfAbsent(dataSource.getDeviceId(), ds -> {
|
||||
final JCheckBox jCheckBox = new JCheckBox(dsName, initialState);
|
||||
jCheckBox.addItemListener(validationListener);
|
||||
devicesListPane.add(jCheckBox);
|
||||
return jCheckBox;
|
||||
});
|
||||
if(devicesMap.containsKey(dataSource.getDeviceId())) {
|
||||
continue;
|
||||
}
|
||||
|
||||
final JCheckBox jCheckBox = new JCheckBox(dsName, selected);
|
||||
jCheckBox.addItemListener(validationListener);
|
||||
devicesListPane.add(jCheckBox);
|
||||
devicesMap.put(dataSource.getDeviceId(), jCheckBox);
|
||||
|
||||
newOneFound = true;
|
||||
|
||||
}
|
||||
} catch (NoCurrentCaseException ex) {
|
||||
logger.log(Level.INFO, "Filter update cancelled. Case is closed.");
|
||||
} catch (TskCoreException tskCoreException) {
|
||||
logger.log(Level.SEVERE, "There was a error loading the datasources for the case.", tskCoreException);
|
||||
}
|
||||
|
||||
if(newOneFound) {
|
||||
devicesListPane.revalidate();
|
||||
}
|
||||
|
||||
return newOneFound;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -319,7 +389,7 @@ final public class FiltersPanel extends JPanel {
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the state of the device filter checkboxes
|
||||
* Sets the state of the device filter check boxes
|
||||
*
|
||||
* @param deviceFilter Selected devices
|
||||
*/
|
||||
@ -366,6 +436,12 @@ final public class FiltersPanel extends JPanel {
|
||||
endDatePicker.setEnabled(state.isEnabled());
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the state of the most recent UI controls based on the current values
|
||||
* in MostRecentFilter.
|
||||
*
|
||||
* @param filter The MostRecentFilter state to be set
|
||||
*/
|
||||
private void setMostRecentFilter(MostRecentFilter filter) {
|
||||
int limit = filter.getLimit();
|
||||
if(limit > 0) {
|
||||
@ -424,6 +500,7 @@ final public class FiltersPanel extends JPanel {
|
||||
gridBagConstraints.gridx = 1;
|
||||
gridBagConstraints.gridy = 0;
|
||||
gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHEAST;
|
||||
gridBagConstraints.insets = new java.awt.Insets(0, 0, 0, 5);
|
||||
topPane.add(applyFiltersButton, gridBagConstraints);
|
||||
|
||||
needsRefreshLabel.setText(org.openide.util.NbBundle.getMessage(FiltersPanel.class, "FiltersPanel.needsRefreshLabel.text")); // NOI18N
|
||||
@ -697,7 +774,7 @@ final public class FiltersPanel extends JPanel {
|
||||
|
||||
accountTypesScrollPane.setPreferredSize(new java.awt.Dimension(2, 200));
|
||||
|
||||
accountTypeListPane.setLayout(new javax.swing.BoxLayout(accountTypeListPane, javax.swing.BoxLayout.Y_AXIS));
|
||||
accountTypeListPane.setLayout(new javax.swing.BoxLayout(accountTypeListPane, javax.swing.BoxLayout.PAGE_AXIS));
|
||||
accountTypesScrollPane.setViewportView(accountTypeListPane);
|
||||
|
||||
gridBagConstraints = new java.awt.GridBagConstraints();
|
||||
@ -740,6 +817,7 @@ final public class FiltersPanel extends JPanel {
|
||||
gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
|
||||
gridBagConstraints.weightx = 1.0;
|
||||
gridBagConstraints.weighty = 1.0;
|
||||
gridBagConstraints.insets = new java.awt.Insets(9, 0, 0, 0);
|
||||
add(scrollPane, gridBagConstraints);
|
||||
}// </editor-fold>//GEN-END:initComponents
|
||||
|
||||
@ -808,6 +886,11 @@ final public class FiltersPanel extends JPanel {
|
||||
endCheckBox.isSelected() ? endDatePicker.getDate().atStartOfDay(zone).toEpochSecond() : 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a MostRecentFilter that based on the current state of the ui controls.
|
||||
*
|
||||
* @return A new instance of MostRecentFilter
|
||||
*/
|
||||
private MostRecentFilter getMostRecentFilter() {
|
||||
String value = (String)limitComboBox.getSelectedItem();
|
||||
if(value.trim().equalsIgnoreCase("all")){
|
||||
|
@ -1845,7 +1845,8 @@ final public class Accounts implements AutopsyVisitableItem {
|
||||
return ICON_BASE_PATH + "WhatsApp.png";
|
||||
} else {
|
||||
//there could be a default icon instead...
|
||||
throw new IllegalArgumentException("Unknown Account.Type: " + type.getTypeName());
|
||||
return ICON_BASE_PATH + "face.png";
|
||||
// throw new IllegalArgumentException("Unknown Account.Type: " + type.getTypeName());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -41,6 +41,8 @@ from org.sleuthkit.datamodel import Content
|
||||
from org.sleuthkit.datamodel import TskCoreException
|
||||
from org.sleuthkit.datamodel import Account
|
||||
from org.sleuthkit.datamodel import Relationship
|
||||
from org.sleuthkit.autopsy.ingest import IngestServices
|
||||
from org.sleuthkit.autopsy.ingest import ModuleDataEvent
|
||||
|
||||
import traceback
|
||||
import general
|
||||
@ -78,7 +80,8 @@ class WWFMessageAnalyzer(general.AndroidComponentAnalyzer):
|
||||
def __findWWFMessagesInDB(self, databasePath, abstractFile, dataSource):
|
||||
if not databasePath:
|
||||
return
|
||||
|
||||
|
||||
bbartifacts = list()
|
||||
try:
|
||||
Class.forName("org.sqlite.JDBC"); # load JDBC driver
|
||||
connection = DriverManager.getConnection("jdbc:sqlite:" + databasePath)
|
||||
@ -115,6 +118,7 @@ class WWFMessageAnalyzer(general.AndroidComponentAnalyzer):
|
||||
attributes.add(BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_MSG_ID, general.MODULE_NAME, game_id))
|
||||
attributes.add(BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_TEXT, general.MODULE_NAME, message))
|
||||
attributes.add(BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_MESSAGE_TYPE, general.MODULE_NAME, "Words With Friends Message"))
|
||||
attributes.add(BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_THREAD_ID, general.MODULE_NAME, user_id))
|
||||
|
||||
artifact.addAttributes(attributes)
|
||||
|
||||
@ -124,6 +128,7 @@ class WWFMessageAnalyzer(general.AndroidComponentAnalyzer):
|
||||
# create relationship between accounts
|
||||
Case.getCurrentCase().getSleuthkitCase().getCommunicationsManager().addRelationships(deviceAccountInstance, [wwfAccountInstance], artifact,Relationship.Type.MESSAGE, created_at);
|
||||
|
||||
bbartifacts.append(artifact)
|
||||
try:
|
||||
# index the artifact for keyword search
|
||||
blackboard = Case.getCurrentCase().getServices().getBlackboard()
|
||||
@ -140,6 +145,10 @@ class WWFMessageAnalyzer(general.AndroidComponentAnalyzer):
|
||||
self._logger.log(Level.SEVERE, "Error parsing WWF messages to the blackboard", ex)
|
||||
self._logger.log(Level.SEVERE, traceback.format_exc())
|
||||
finally:
|
||||
if bbartifacts:
|
||||
|
||||
IngestServices.getInstance().fireModuleDataEvent(ModuleDataEvent(general.MODULE_NAME, BlackboardArtifact.ARTIFACT_TYPE.TSK_MESSAGE, bbartifacts))
|
||||
|
||||
try:
|
||||
if resultSet is not None:
|
||||
resultSet.close()
|
||||
|
Loading…
x
Reference in New Issue
Block a user