19 package org.sleuthkit.autopsy.datamodel.accounts;
21 import com.google.common.collect.Range;
22 import com.google.common.collect.RangeMap;
23 import com.google.common.collect.TreeRangeMap;
24 import com.google.common.eventbus.EventBus;
25 import com.google.common.eventbus.Subscribe;
26 import java.awt.event.ActionEvent;
27 import java.beans.PropertyChangeEvent;
28 import java.beans.PropertyChangeListener;
29 import java.sql.ResultSet;
30 import java.sql.SQLException;
31 import java.util.ArrayList;
32 import java.util.Arrays;
33 import java.util.Collection;
34 import java.util.Collections;
35 import java.util.EnumSet;
36 import java.util.HashMap;
37 import java.util.HashSet;
38 import java.util.List;
40 import java.util.Objects;
41 import java.util.Optional;
43 import java.util.function.Function;
44 import java.util.logging.Level;
45 import java.util.stream.Collectors;
46 import java.util.stream.Stream;
47 import javax.annotation.Nonnull;
48 import javax.annotation.concurrent.Immutable;
49 import javax.swing.AbstractAction;
50 import javax.swing.Action;
51 import javax.swing.SwingUtilities;
52 import org.apache.commons.lang3.StringUtils;
53 import org.openide.nodes.ChildFactory;
54 import org.openide.nodes.Children;
55 import org.openide.nodes.Node;
56 import org.openide.nodes.NodeNotFoundException;
57 import org.openide.nodes.NodeOp;
58 import org.openide.nodes.Sheet;
59 import org.openide.util.NbBundle;
60 import org.openide.util.Utilities;
61 import org.openide.util.WeakListeners;
62 import org.openide.util.lookup.Lookups;
83 import static org.
sleuthkit.datamodel.BlackboardArtifact.Type.TSK_ACCOUNT;
98 private static final String
ICON_BASE_PATH =
"/org/sleuthkit/autopsy/images/";
101 private static final String
DISPLAY_NAME = Bundle.Accounts_RootNode_displayName();
103 @NbBundle.Messages(
"AccountsRootNode.name=Accounts")
104 final public static String
NAME = Bundle.AccountsRootNode_name();
137 this.filteringDSObjId = objId;
146 return visitor.
visit(
this);
157 return showRejected ?
" " :
" AND blackboard_artifacts.review_status_id != " + BlackboardArtifact.ReviewStatus.REJECTED.getID() +
" ";
167 if (filteringDSObjId > 0) {
168 return " AND blackboard_artifacts.data_source_obj_id = " + filteringDSObjId +
" ";
207 abstract protected boolean createKeys(List<X> list);
237 @NbBundle.Messages({
"Accounts.RootNode.displayName=Communication Accounts"})
248 this.setIconBaseWithExtension(
"org/sleuthkit/autopsy/images/accounts.png");
258 return visitor.
visit(
this);
263 return getClass().getName();
268 String accountTypesInUseQuery
269 =
"SELECT COUNT(*) AS count\n"
271 +
" SELECT MIN(blackboard_attributes.value_text) AS account_type\n"
272 +
" FROM blackboard_artifacts\n"
273 +
" LEFT JOIN blackboard_attributes ON blackboard_artifacts.artifact_id = blackboard_attributes.artifact_id\n"
274 +
" WHERE blackboard_artifacts.artifact_type_id = " + TSK_ACCOUNT.getTypeID() +
"\n"
275 +
" AND blackboard_attributes.attribute_type_id = " + BlackboardAttribute.Type.TSK_ACCOUNT_TYPE.getTypeID() +
"\n"
276 +
" AND blackboard_attributes.value_text IS NOT NULL\n"
278 +
" -- group by artifact_id to ensure only one account type per artifact\n"
279 +
" GROUP BY blackboard_artifacts.artifact_id\n"
283 ResultSet resultSet = executeQuery.getResultSet()) {
285 if (resultSet.next()) {
286 return resultSet.getLong(
"count");
290 LOGGER.log(Level.SEVERE,
"Error querying for count of all account types", ex);
303 private final Map<String, Long>
counts =
new HashMap<>();
317 Long getCount(String accountType) {
318 return counts.get(accountType);
326 List<String> getTypes() {
327 List<String> types =
new ArrayList<>(counts.keySet());
328 Collections.sort(types);
336 String accountTypesInUseQuery
337 =
"SELECT res.account_type, COUNT(*) AS count\n"
339 +
" SELECT MIN(blackboard_attributes.value_text) AS account_type\n"
340 +
" FROM blackboard_artifacts\n"
341 +
" LEFT JOIN blackboard_attributes ON blackboard_artifacts.artifact_id = blackboard_attributes.artifact_id\n"
342 +
" WHERE blackboard_artifacts.artifact_type_id = " + TSK_ACCOUNT.getTypeID() +
"\n"
343 +
" AND blackboard_attributes.attribute_type_id = " + BlackboardAttribute.Type.TSK_ACCOUNT_TYPE.getTypeID() +
"\n"
345 +
" -- group by artifact_id to ensure only one account type per artifact\n"
346 +
" GROUP BY blackboard_artifacts.artifact_id\n"
348 +
"GROUP BY res.account_type";
351 ResultSet resultSet = executeQuery.getResultSet()) {
354 while (resultSet.next()) {
355 String accountType = resultSet.getString(
"account_type");
356 Long count = resultSet.getLong(
"count");
357 counts.put(accountType, count);
360 LOGGER.log(Level.SEVERE,
"Error querying for account_types", ex);
374 private final PropertyChangeListener
pcl =
new PropertyChangeListener() {
376 public void propertyChange(PropertyChangeEvent evt) {
377 String eventType = evt.getPropertyName();
394 if (null != eventData
396 accountTypeResults.
update();
397 reviewStatusBus.post(eventData);
412 accountTypeResults.
update();
421 private final PropertyChangeListener
weakPcl = WeakListeners.propertyChange(pcl, null);
437 list.addAll(accountTypeResults.getTypes());
450 reviewStatusBus.register(node);
451 return new Node[]{node};
457 if (Account.Type.CREDIT_CARD.getTypeName().equals(accountTypeName)) {
463 if (accountType != null) {
467 LOGGER.log(Level.SEVERE,
"Unknown account type '" + accountTypeName +
"' found - account will not be displayed.\n"
468 +
"Account type names must match an entry in the display_name column of the account_types table.\n"
469 +
"Accounts should be created using the CommunicationManager API.");
472 LOGGER.log(Level.SEVERE,
"Error getting display name for account type. ", ex);
506 private final PropertyChangeListener pcl =
new PropertyChangeListener() {
508 public void propertyChange(PropertyChangeEvent evt) {
509 String eventType = evt.getPropertyName();
526 if (null != eventData
528 reviewStatusBus.post(eventData);
552 private final PropertyChangeListener weakPcl = WeakListeners.propertyChange(pcl, null);
572 =
"SELECT blackboard_artifacts.artifact_obj_id "
573 +
" FROM blackboard_artifacts "
574 +
" JOIN blackboard_attributes ON blackboard_artifacts.artifact_id = blackboard_attributes.artifact_id "
575 +
" WHERE blackboard_artifacts.artifact_type_id = " + BlackboardArtifact.Type.TSK_ACCOUNT.getTypeID()
576 +
" AND blackboard_attributes.attribute_type_id = " + BlackboardAttribute.ATTRIBUTE_TYPE.TSK_ACCOUNT_TYPE.getTypeID()
577 +
" AND blackboard_attributes.value_text = '" + accountType.getTypeName() +
"'"
581 ResultSet rs = results.getResultSet();) {
582 List<Long> tempList =
new ArrayList<>();
584 tempList.add(rs.getLong(
"artifact_obj_id"));
586 list.addAll(tempList);
588 LOGGER.log(Level.SEVERE,
"Error querying for account artifacts.", ex);
599 LOGGER.log(Level.SEVERE,
"Error get black board artifact with id " + t, ex);
626 super(Children.create(
new DefaultAccountFactory(accountType),
true), Lookups.singleton(accountType));
629 this.setIconBaseWithExtension(iconPath != null && iconPath.charAt(0) ==
'/' ? iconPath.substring(1) : iconPath);
630 setName(accountType.getTypeName());
641 return visitor.
visit(
this);
646 return getClass().getName();
664 setDisplayName(String.format(
"%s (%d)", accountType.getDisplayName(), accountTypeResults.getCount(accountType.getTypeName())));
678 private final PropertyChangeListener pcl =
new PropertyChangeListener() {
680 public void propertyChange(PropertyChangeEvent evt) {
681 String eventType = evt.getPropertyName();
698 if (null != eventData
700 reviewStatusBus.post(eventData);
724 private final PropertyChangeListener weakPcl = WeakListeners.propertyChange(pcl, null);
752 super.removeNotify();
759 protected boolean createKeys(List<CreditCardViewMode> list) {
788 super(Children.create(
new ViewModeFactory(),
true), Lookups.singleton(Account.Type.CREDIT_CARD.getDisplayName()));
789 setName(Account.Type.CREDIT_CARD.getDisplayName());
790 this.setIconBaseWithExtension(
"org/sleuthkit/autopsy/images/credit-cards.png");
798 setName(String.format(
"%s (%d)", Account.Type.CREDIT_CARD.getDisplayName(), accountTypeResults.getCount(Account.Type.CREDIT_CARD.getTypeName())));
818 return visitor.
visit(
this);
823 return getClass().getName();
829 private final PropertyChangeListener pcl =
new PropertyChangeListener() {
831 public void propertyChange(PropertyChangeEvent evt) {
832 String eventType = evt.getPropertyName();
849 if (null != eventData
851 reviewStatusBus.post(eventData);
875 private final PropertyChangeListener weakPcl = WeakListeners.propertyChange(pcl, null);
909 =
"SELECT blackboard_artifacts.obj_id,"
910 +
" solr_attribute.value_text AS solr_document_id, ";
912 query +=
" string_agg(blackboard_artifacts.artifact_id::character varying, ',') AS artifact_IDs, "
913 +
" string_agg(blackboard_artifacts.review_status_id::character varying, ',') AS review_status_ids, ";
915 query +=
" GROUP_CONCAT(blackboard_artifacts.artifact_id) AS artifact_IDs, "
916 +
" GROUP_CONCAT(blackboard_artifacts.review_status_id) AS review_status_ids, ";
918 query +=
" COUNT( blackboard_artifacts.artifact_id) AS hits "
919 +
" FROM blackboard_artifacts "
920 +
" LEFT JOIN blackboard_attributes as solr_attribute ON blackboard_artifacts.artifact_id = solr_attribute.artifact_id "
921 +
" AND solr_attribute.attribute_type_id = " + BlackboardAttribute.ATTRIBUTE_TYPE.TSK_KEYWORD_SEARCH_DOCUMENT_ID.getTypeID()
922 +
" LEFT JOIN blackboard_attributes as account_type ON blackboard_artifacts.artifact_id = account_type.artifact_id "
923 +
" AND account_type.attribute_type_id = " + BlackboardAttribute.ATTRIBUTE_TYPE.TSK_ACCOUNT_TYPE.getTypeID()
924 +
" AND account_type.value_text = '" + Account.Type.CREDIT_CARD.getTypeName() +
"'"
925 +
" WHERE blackboard_artifacts.artifact_type_id = " + BlackboardArtifact.Type.TSK_ACCOUNT.getTypeID()
928 +
" GROUP BY blackboard_artifacts.obj_id, solr_document_id "
929 +
" ORDER BY hits DESC ";
931 ResultSet resultSet = results.getResultSet();) {
932 while (resultSet.next()) {
933 long file_id = resultSet.getLong(
"obj_id");
935 if (abstractFileById != null) {
939 resultSet.getString(
"solr_document_id"),
940 unGroupConcat(resultSet.getString(
"artifact_IDs"), Long::valueOf),
941 resultSet.getLong(
"hits"),
942 new HashSet<>(unGroupConcat(resultSet.getString(
"review_status_ids"), reviewStatusID -> BlackboardArtifact.ReviewStatus.withID(Integer.valueOf(reviewStatusID))))));
945 }
catch (TskCoreException | SQLException ex) {
946 LOGGER.log(Level.SEVERE,
"Error querying for files with ccn hits.", ex);
950 LOGGER.log(Level.SEVERE,
"Error getting case.", ex);
959 List<Object> lookupContents =
new ArrayList<>();
963 AbstractFile abstractFileById = key.getFile();
964 lookupContents.add(abstractFileById);
965 return new Node[]{
new FileWithCCNNode(key, abstractFileById, lookupContents.toArray())};
967 LOGGER.log(Level.SEVERE,
"Error getting content for file with ccn hits.", ex);
986 this.setIconBaseWithExtension(
"org/sleuthkit/autopsy/images/file-icon.png");
987 reviewStatusBus.register(
this);
991 "# {0} - number of children",
992 "Accounts.ByFileNode.displayName=By File ({0})"})
995 =
"SELECT count(*) FROM ( SELECT count(*) AS documents "
996 +
" FROM blackboard_artifacts "
997 +
" LEFT JOIN blackboard_attributes as solr_attribute ON blackboard_artifacts.artifact_id = solr_attribute.artifact_id "
998 +
" AND solr_attribute.attribute_type_id = " + BlackboardAttribute.ATTRIBUTE_TYPE.TSK_KEYWORD_SEARCH_DOCUMENT_ID.getTypeID()
999 +
" LEFT JOIN blackboard_attributes as account_type ON blackboard_artifacts.artifact_id = account_type.artifact_id "
1000 +
" AND account_type.attribute_type_id = " + BlackboardAttribute.ATTRIBUTE_TYPE.TSK_ACCOUNT_TYPE.getTypeID()
1001 +
" AND account_type.value_text = '" + Account.Type.CREDIT_CARD.getTypeName() +
"'"
1002 +
" WHERE blackboard_artifacts.artifact_type_id = " + BlackboardArtifact.Type.TSK_ACCOUNT.getTypeID()
1005 +
" GROUP BY blackboard_artifacts.obj_id, solr_attribute.value_text ) AS foo";
1007 ResultSet resultSet = results.getResultSet();) {
1008 while (resultSet.next()) {
1010 setDisplayName(Bundle.Accounts_ByFileNode_displayName(resultSet.getLong(
"count")));
1012 setDisplayName(Bundle.Accounts_ByFileNode_displayName(resultSet.getLong(
"count(*)")));
1016 LOGGER.log(Level.SEVERE,
"Error querying for files with ccn hits.", ex);
1028 return visitor.
visit(
this);
1033 return getClass().getName();
1038 updateDisplayName();
1043 updateDisplayName();
1049 private final PropertyChangeListener pcl =
new PropertyChangeListener() {
1051 public void propertyChange(PropertyChangeEvent evt) {
1052 String eventType = evt.getPropertyName();
1069 if (null != eventData
1071 reviewStatusBus.post(eventData);
1095 private final PropertyChangeListener weakPcl = WeakListeners.propertyChange(pcl, null);
1128 RangeMap<Integer, BinResult> binRanges = TreeRangeMap.create();
1131 =
"SELECT SUBSTR(blackboard_attributes.value_text,1,8) AS BIN, "
1132 +
" COUNT(blackboard_artifacts.artifact_id) AS count "
1133 +
" FROM blackboard_artifacts "
1134 +
" JOIN blackboard_attributes ON blackboard_artifacts.artifact_id = blackboard_attributes.artifact_id"
1135 +
" WHERE blackboard_artifacts.artifact_type_id = " + BlackboardArtifact.Type.TSK_ACCOUNT.getTypeID()
1136 +
" AND blackboard_attributes.attribute_type_id = " + BlackboardAttribute.ATTRIBUTE_TYPE.TSK_CARD_NUMBER.getTypeID()
1142 ResultSet resultSet = results.getResultSet();) {
1144 while (resultSet.next()) {
1145 final Integer bin = Integer.valueOf(resultSet.getString(
"BIN"));
1146 long count = resultSet.getLong(
"count");
1149 BinResult previousResult = binRanges.get(bin);
1151 if (previousResult != null) {
1152 binRanges.remove(Range.closed(previousResult.getBINStart(), previousResult.getBINEnd()));
1153 count += previousResult.getCount();
1156 if (binRange == null) {
1157 binRanges.put(Range.closed(bin, bin),
new BinResult(count, bin, bin));
1162 binRanges.asMapOfRanges().values().forEach(list::add);
1164 LOGGER.log(Level.SEVERE,
"Error querying for BINs.", ex);
1172 return new Node[]{
new BINNode(key)};
1185 @NbBundle.Messages(
"Accounts.ByBINNode.name=By BIN")
1187 super(Children.create(
new BINFactory(),
true), Lookups.singleton(Bundle.Accounts_ByBINNode_name()));
1188 setName(Bundle.Accounts_ByBINNode_name());
1189 updateDisplayName();
1190 this.setIconBaseWithExtension(
"org/sleuthkit/autopsy/images/bank.png");
1191 reviewStatusBus.register(
this);
1194 @NbBundle.Messages({
1195 "# {0} - number of children",
1196 "Accounts.ByBINNode.displayName=By BIN ({0})"})
1199 =
"SELECT count(distinct SUBSTR(blackboard_attributes.value_text,1,8)) AS BINs "
1200 +
" FROM blackboard_artifacts "
1201 +
" JOIN blackboard_attributes ON blackboard_artifacts.artifact_id = blackboard_attributes.artifact_id"
1202 +
" WHERE blackboard_artifacts.artifact_type_id = " + BlackboardArtifact.Type.TSK_ACCOUNT.getTypeID()
1203 +
" AND blackboard_attributes.attribute_type_id = " + BlackboardAttribute.ATTRIBUTE_TYPE.TSK_CARD_NUMBER.getTypeID()
1207 ResultSet resultSet = results.getResultSet();) {
1208 while (resultSet.next()) {
1209 setDisplayName(Bundle.Accounts_ByBINNode_displayName(resultSet.getLong(
"BINs")));
1212 LOGGER.log(Level.SEVERE,
"Error querying for BINs.", ex);
1223 return visitor.
visit(
this);
1228 return getClass().getName();
1233 updateDisplayName();
1238 updateDisplayName();
1252 hash = 79 * hash + (int) (this.objID ^ (this.objID >>> 32));
1253 hash = 79 * hash + Objects.hashCode(this.keywordSearchDocID);
1254 hash = 79 * hash + Objects.hashCode(this.artifactIDs);
1255 hash = 79 * hash + (int) (this.hits ^ (this.hits >>> 32));
1256 hash = 79 * hash + Objects.hashCode(this.statuses);
1268 if (getClass() != obj.getClass()) {
1272 if (this.objID != other.
objID) {
1275 if (this.hits != other.
hits) {
1281 if (!Objects.equals(
this.artifactIDs, other.
artifactIDs)) {
1284 if (!Objects.equals(
this.statuses, other.
statuses)) {
1294 private final Set<BlackboardArtifact.ReviewStatus>
statuses;
1297 private FileWithCCN(AbstractFile file,
long objID, String solrDocID, List<Long> artifactIDs,
long hits, Set<BlackboardArtifact.ReviewStatus> statuses) {
1299 this.keywordSearchDocID = solrDocID;
1300 this.artifactIDs = artifactIDs;
1302 this.statuses = statuses;
1322 return keywordSearchDocID;
1331 return Collections.unmodifiableList(artifactIDs);
1349 return Collections.unmodifiableSet(statuses);
1352 AbstractFile getFile() {
1373 static <X> List<X> unGroupConcat(String groupConcat, Function<String, X> mapper) {
1374 return StringUtils.isBlank(groupConcat) ? Collections.emptyList()
1375 : Stream.of(groupConcat.split(
","))
1377 .collect(Collectors.toList());
1397 @NbBundle.Messages({
1398 "# {0} - raw file name",
1399 "# {1} - solr chunk id",
1400 "Accounts.FileWithCCNNode.unallocatedSpaceFile.displayName={0}_chunk_{1}"})
1402 super(Children.LEAF, Lookups.fixed(lookupContents));
1406 : Bundle.Accounts_FileWithCCNNode_unallocatedSpaceFile_displayName(content.getName(), StringUtils.substringAfter(key.
getkeywordSearchDocID(),
"_"));
1407 setName(fileName + key.
getObjID());
1408 setDisplayName(fileName);
1418 return visitor.
visit(
this);
1423 return getClass().getName();
1427 @NbBundle.Messages({
1428 "Accounts.FileWithCCNNode.nameProperty.displayName=File",
1429 "Accounts.FileWithCCNNode.accountsProperty.displayName=Accounts",
1430 "Accounts.FileWithCCNNode.statusProperty.displayName=Status",
1431 "Accounts.FileWithCCNNode.noDescription=no description"})
1433 Sheet sheet = super.createSheet();
1434 Sheet.Set propSet = sheet.get(Sheet.PROPERTIES);
1435 if (propSet == null) {
1436 propSet = Sheet.createPropertiesSet();
1440 propSet.put(
new NodeProperty<>(Bundle.Accounts_FileWithCCNNode_nameProperty_displayName(),
1441 Bundle.Accounts_FileWithCCNNode_nameProperty_displayName(),
1442 Bundle.Accounts_FileWithCCNNode_noDescription(),
1444 propSet.put(
new NodeProperty<>(Bundle.Accounts_FileWithCCNNode_accountsProperty_displayName(),
1445 Bundle.Accounts_FileWithCCNNode_accountsProperty_displayName(),
1446 Bundle.Accounts_FileWithCCNNode_noDescription(),
1448 propSet.put(
new NodeProperty<>(Bundle.Accounts_FileWithCCNNode_statusProperty_displayName(),
1449 Bundle.Accounts_FileWithCCNNode_statusProperty_displayName(),
1450 Bundle.Accounts_FileWithCCNNode_noDescription(),
1452 .map(BlackboardArtifact.ReviewStatus::getDisplayName)
1453 .collect(Collectors.joining(
", "))));
1460 Action[] actions = super.getActions(context);
1461 ArrayList<Action> arrayList =
new ArrayList<>();
1465 LOGGER.log(Level.SEVERE,
"Error gettung content by id", ex);
1468 arrayList.add(approveActionInstance);
1469 arrayList.add(rejectActionInstance);
1470 arrayList.add(null);
1471 arrayList.addAll(Arrays.asList(actions));
1472 return arrayList.toArray(
new Action[arrayList.size()]);
1500 =
"SELECT blackboard_artifacts.artifact_obj_id "
1501 +
" FROM blackboard_artifacts "
1502 +
" JOIN blackboard_attributes ON blackboard_artifacts.artifact_id = blackboard_attributes.artifact_id "
1503 +
" WHERE blackboard_artifacts.artifact_type_id = " + BlackboardArtifact.Type.TSK_ACCOUNT.getTypeID()
1504 +
" AND blackboard_attributes.attribute_type_id = " + BlackboardAttribute.ATTRIBUTE_TYPE.TSK_CARD_NUMBER.getTypeID()
1505 +
" AND blackboard_attributes.value_text >= '" + bin.getBINStart() +
"' AND blackboard_attributes.value_text < '" + (bin.getBINEnd() + 1) +
"'"
1508 +
" ORDER BY blackboard_attributes.value_text";
1510 ResultSet rs = results.getResultSet();) {
1515 LOGGER.log(Level.SEVERE,
"Error querying for account artifacts.", ex);
1528 if (bin.getBINStart() == bin.getBINEnd()) {
1529 return Integer.toString(bin.getBINStart());
1531 return bin.getBINStart() +
"-" + StringUtils.difference(bin.getBINStart() +
"", bin.getBINEnd() +
"");
1546 updateDisplayName();
1547 this.setIconBaseWithExtension(
"org/sleuthkit/autopsy/images/bank.png");
1548 reviewStatusBus.register(
this);
1553 updateDisplayName();
1559 updateDisplayName();
1564 =
"SELECT count(blackboard_artifacts.artifact_id ) AS count"
1565 +
" FROM blackboard_artifacts "
1566 +
" JOIN blackboard_attributes ON blackboard_artifacts.artifact_id = blackboard_attributes.artifact_id "
1567 +
" WHERE blackboard_artifacts.artifact_type_id = " + BlackboardArtifact.Type.TSK_ACCOUNT.getTypeID()
1568 +
" AND blackboard_attributes.attribute_type_id = " + BlackboardAttribute.ATTRIBUTE_TYPE.TSK_CARD_NUMBER.getTypeID()
1569 +
" AND blackboard_attributes.value_text >= '" + bin.getBINStart() +
"' AND blackboard_attributes.value_text < '" + (bin.getBINEnd() + 1) +
"'"
1573 ResultSet resultSet = results.getResultSet();) {
1574 while (resultSet.next()) {
1575 setDisplayName(
getBinRangeString(bin) +
" (" + resultSet.getLong(
"count") +
")");
1578 LOGGER.log(Level.SEVERE,
"Error querying for account artifacts.", ex);
1591 return visitor.
visit(
this);
1596 return getClass().getName();
1600 Sheet.Set sheetSet = sheet.get(Sheet.PROPERTIES);
1601 if (sheetSet == null) {
1602 sheetSet = Sheet.createPropertiesSet();
1603 sheet.put(sheetSet);
1609 @NbBundle.Messages({
1610 "Accounts.BINNode.binProperty.displayName=Bank Identifier Number",
1611 "Accounts.BINNode.accountsProperty.displayName=Accounts",
1612 "Accounts.BINNode.cardTypeProperty.displayName=Payment Card Type",
1613 "Accounts.BINNode.schemeProperty.displayName=Credit Card Scheme",
1614 "Accounts.BINNode.brandProperty.displayName=Brand",
1615 "Accounts.BINNode.bankProperty.displayName=Bank",
1616 "Accounts.BINNode.bankCityProperty.displayName=Bank City",
1617 "Accounts.BINNode.bankCountryProperty.displayName=Bank Country",
1618 "Accounts.BINNode.bankPhoneProperty.displayName=Bank Phone #",
1619 "Accounts.BINNode.bankURLProperty.displayName=Bank URL",
1620 "Accounts.BINNode.noDescription=no description"})
1622 Sheet sheet = super.createSheet();
1623 Sheet.Set properties = getPropertySet(sheet);
1625 properties.put(
new NodeProperty<>(Bundle.Accounts_BINNode_binProperty_displayName(),
1626 Bundle.Accounts_BINNode_binProperty_displayName(),
1627 Bundle.Accounts_BINNode_noDescription(),
1629 properties.put(
new NodeProperty<>(Bundle.Accounts_BINNode_accountsProperty_displayName(),
1630 Bundle.Accounts_BINNode_accountsProperty_displayName(), Bundle.Accounts_BINNode_noDescription(),
1634 if (bin.hasDetails()) {
1635 bin.
getCardType().ifPresent(cardType -> properties.put(
new NodeProperty<>(Bundle.Accounts_BINNode_cardTypeProperty_displayName(),
1636 Bundle.Accounts_BINNode_cardTypeProperty_displayName(), Bundle.Accounts_BINNode_noDescription(),
1638 bin.
getScheme().ifPresent(scheme -> properties.put(
new NodeProperty<>(Bundle.Accounts_BINNode_schemeProperty_displayName(),
1639 Bundle.Accounts_BINNode_schemeProperty_displayName(), Bundle.Accounts_BINNode_noDescription(),
1641 bin.
getBrand().ifPresent(brand -> properties.put(
new NodeProperty<>(Bundle.Accounts_BINNode_brandProperty_displayName(),
1642 Bundle.Accounts_BINNode_brandProperty_displayName(), Bundle.Accounts_BINNode_noDescription(),
1644 bin.
getBankName().ifPresent(bankName -> properties.put(
new NodeProperty<>(Bundle.Accounts_BINNode_bankProperty_displayName(),
1645 Bundle.Accounts_BINNode_bankProperty_displayName(), Bundle.Accounts_BINNode_noDescription(),
1647 bin.
getBankCity().ifPresent(bankCity -> properties.put(
new NodeProperty<>(Bundle.Accounts_BINNode_bankCityProperty_displayName(),
1648 Bundle.Accounts_BINNode_bankCityProperty_displayName(), Bundle.Accounts_BINNode_noDescription(),
1650 bin.
getCountry().ifPresent(country -> properties.put(
new NodeProperty<>(Bundle.Accounts_BINNode_bankCountryProperty_displayName(),
1651 Bundle.Accounts_BINNode_bankCountryProperty_displayName(), Bundle.Accounts_BINNode_noDescription(),
1654 Bundle.Accounts_BINNode_bankPhoneProperty_displayName(), Bundle.Accounts_BINNode_noDescription(),
1656 bin.
getBankURL().ifPresent(url -> properties.put(
new NodeProperty<>(Bundle.Accounts_BINNode_bankURLProperty_displayName(),
1657 Bundle.Accounts_BINNode_bankURLProperty_displayName(), Bundle.Accounts_BINNode_noDescription(),
1664 SwingUtilities.invokeLater(() -> {
1665 this.setSheet(createSheet());
1681 hash = 97 * hash + this.binEnd;
1682 hash = 97 * hash + this.binStart;
1694 if (getClass() != obj.getClass()) {
1698 if (this.binEnd != other.
binEnd) {
1701 if (this.binStart != other.
binStart) {
1718 this.binRange = binRange;
1719 binStart = binRange.getBINstart();
1720 binEnd = binRange.getBINend();
1725 this.binRange = null;
1742 boolean hasDetails() {
1743 return binRange != null;
1797 super(artifact,
"org/sleuthkit/autopsy/images/credit-card.png");
1798 this.artifact = artifact;
1799 setName(Long.toString(
this.artifact.getArtifactID()));
1801 reviewStatusBus.register(
this);
1806 List<Action> actionsList =
new ArrayList<>();
1807 actionsList.addAll(Arrays.asList(super.getActions(context)));
1809 actionsList.add(approveActionInstance);
1810 actionsList.add(rejectActionInstance);
1812 return actionsList.toArray(
new Action[actionsList.size()]);
1817 Sheet sheet = super.createSheet();
1818 Sheet.Set properties = sheet.get(Sheet.PROPERTIES);
1819 if (properties == null) {
1820 properties = Sheet.createPropertiesSet();
1821 sheet.put(properties);
1823 properties.put(
new NodeProperty<>(Bundle.Accounts_FileWithCCNNode_statusProperty_displayName(),
1824 Bundle.Accounts_FileWithCCNNode_statusProperty_displayName(),
1825 Bundle.Accounts_FileWithCCNNode_noDescription(),
1826 artifact.getReviewStatus().getDisplayName()));
1835 event.artifacts.stream().filter((art) -> (art.getArtifactID() == this.artifact.getArtifactID())).map((_item) -> {
1837 }).forEachOrdered((_item) -> {
1843 SwingUtilities.invokeLater(() -> {
1844 this.setSheet(createSheet());
1853 @NbBundle.Messages(
"ToggleShowRejected.name=Show Rejected Results")
1855 super(Bundle.ToggleShowRejected_name());
1881 this.newStatus = newStatus;
1892 List<String[]> selectedPaths = Utilities.actionsGlobalContext().lookupAll(Node.class).stream()
1894 String[] createPath;
1900 if (newStatus == BlackboardArtifact.ReviewStatus.REJECTED && showRejected ==
false) {
1901 List<Node> siblings = Arrays.asList(node.getParentNode().getChildren().getNodes());
1902 if (siblings.size() > 1) {
1903 int indexOf = siblings.indexOf(node);
1905 Node sibling = indexOf > 0
1906 ? siblings.get(indexOf - 1)
1907 : siblings.get(Integer.max(indexOf + 1, siblings.size() - 1));
1908 createPath = NodeOp.createPath(sibling, null);
1918 createPath = NodeOp.createPath(node, null);
1921 return Arrays.copyOfRange(createPath, 1, createPath.length);
1923 .filter(Objects::nonNull)
1924 .collect(Collectors.toList());
1927 final Collection<? extends BlackboardArtifact> artifacts = Utilities.actionsGlobalContext().lookupAll(BlackboardArtifact.class);
1928 artifacts.forEach(artifact -> {
1930 artifact.setReviewStatus(newStatus);
1931 }
catch (TskCoreException ex) {
1932 LOGGER.log(Level.SEVERE,
"Error changing artifact review status.", ex);
1936 reviewStatusBus.post(
new ReviewStatusChangeEvent(artifacts, newStatus));
1938 final DataResultTopComponent directoryListing = DirectoryTreeTopComponent.findInstance().getDirectoryListing();
1939 final Node rootNode = directoryListing.getRootNode();
1942 List<Node> toArray =
new ArrayList<>();
1943 selectedPaths.forEach(path -> {
1945 toArray.add(NodeOp.findPath(rootNode, path));
1946 }
catch (NodeNotFoundException ex) {
1951 directoryListing.setSelectedNodes(toArray.toArray(
new Node[toArray.size()]));
1957 @NbBundle.Messages({
"ApproveAccountsAction.name=Approve Accounts"})
1959 super(Bundle.ApproveAccountsAction_name(), BlackboardArtifact.ReviewStatus.APPROVED);
1965 @NbBundle.Messages({
"RejectAccountsAction.name=Reject Accounts"})
1967 super(Bundle.RejectAccountsAction_name(), BlackboardArtifact.ReviewStatus.REJECTED);
1973 Collection<? extends BlackboardArtifact> artifacts;
1974 BlackboardArtifact.ReviewStatus newReviewStatus;
1976 ReviewStatusChangeEvent(Collection<? extends BlackboardArtifact> artifacts, BlackboardArtifact.ReviewStatus newReviewStatus) {
1977 this.artifacts = artifacts;
1978 this.newReviewStatus = newReviewStatus;
1989 if (type.equals(Account.Type.CREDIT_CARD)) {
1990 return ICON_BASE_PATH +
"credit-card.png";
1991 }
else if (type.equals(Account.Type.DEVICE)) {
1992 return ICON_BASE_PATH +
"image.png";
1993 }
else if (type.equals(Account.Type.EMAIL)) {
1994 return ICON_BASE_PATH +
"email.png";
1995 }
else if (type.equals(Account.Type.FACEBOOK)) {
1996 return ICON_BASE_PATH +
"facebook.png";
1997 }
else if (type.equals(Account.Type.INSTAGRAM)) {
1998 return ICON_BASE_PATH +
"instagram.png";
1999 }
else if (type.equals(Account.Type.MESSAGING_APP)) {
2000 return ICON_BASE_PATH +
"messaging.png";
2001 }
else if (type.equals(Account.Type.PHONE)) {
2002 return ICON_BASE_PATH +
"phone.png";
2003 }
else if (type.equals(Account.Type.TWITTER)) {
2004 return ICON_BASE_PATH +
"twitter.png";
2005 }
else if (type.equals(Account.Type.WEBSITE)) {
2006 return ICON_BASE_PATH +
"web-file.png";
2007 }
else if (type.equals(Account.Type.WHATSAPP)) {
2008 return ICON_BASE_PATH +
"WhatsApp.png";
2011 return ICON_BASE_PATH +
"face.png";
CreditCardNumberFactory(BinResult bin)
static final Set< IngestManager.IngestModuleEvent > INGEST_MODULE_EVENTS_OF_INTEREST
final BlackboardArtifact.ReviewStatus newStatus
final PropertyChangeListener weakPcl
boolean createKeys(List< CreditCardViewMode > list)
DefaultAccountFactory(Account.Type accountType)
BlackboardArtifact.Type getBlackboardArtifactType()
void removeIngestModuleEventListener(final PropertyChangeListener listener)
Optional< Integer > getNumberLength()
Node[] createNodesForKey(Long t)
Optional< String > getCountry()
final BlackboardArtifact artifact
static synchronized IngestManager getInstance()
String getBinRangeString(BinResult bin)
static final Logger LOGGER
Node[] createNodesForKey(BinResult key)
Optional< String > getBankPhoneNumber()
Set< BlackboardArtifact.ReviewStatus > getStatuses()
void setShowRejected(boolean showRejected)
Optional< String > getCountry()
Sheet.Set getPropertySet(Sheet sheet)
Optional< String > getBankCity()
final String keywordSearchDocID
static List< Action > getActions(File file, boolean isArtifactSource)
Optional< String > getBankName()
final EventBus reviewStatusBus
String getRejectedArtifactFilterClause()
Node[] createNodesForKey(DataArtifact artifact)
boolean createKeys(List< DataArtifact > list)
final PropertyChangeListener weakPcl
final RejectAccounts rejectActionInstance
final Account.Type accountType
List< Long > getArtifactIDs()
boolean createKeys(List< String > list)
abstract boolean createKeys(List< X > list)
AccountArtifactNode(BlackboardArtifact artifact)
static synchronized BankIdentificationNumber getBINInfo(int bin)
Node[] getNodeArr(Node node)
Action[] getActions(boolean context)
Node[] createNodesForKey(FileWithCCN key)
static String getIconFilePath(Account.Type type)
boolean createKeys(List< FileWithCCN > list)
Node[] createNodesForKey(String accountTypeName)
final Account.Type accountType
Optional< String > getBankURL()
boolean createKeys(List< Long > list)
final Map< String, Long > counts
final ApproveAccounts approveActionInstance
final long filteringDSObjId
Node[] createNodesForKey(CreditCardViewMode key)
long fetchChildCount(SleuthkitCase skCase)
void removeIngestJobEventListener(final PropertyChangeListener listener)
Optional< String > getScheme()
final Set< BlackboardArtifact.ReviewStatus > statuses
Optional< String > getBrand()
static final String DISPLAY_NAME
boolean equals(Object obj)
CreditCardNumberAccountTypeNode()
void addIngestJobEventListener(final PropertyChangeListener listener)
DefaultAccountTypeNode(Account.Type accountType)
Optional< String > getBankURL()
String getkeywordSearchDocID()
Optional< Integer > getNumberLength()
BinResult(long count,@Nonnull BINRange binRange)
Action newToggleShowRejectedAction()
Optional< String > getBrand()
SleuthkitCase getSleuthkitCase()
FileWithCCNNode(FileWithCCN key, Content content, Object[] lookupContents)
Action[] getActions(boolean context)
final List< Long > artifactIDs
T visit(DataSourceFilesNode in)
void actionPerformed(ActionEvent e)
boolean createKeys(List< BinResult > list)
FileWithCCN(AbstractFile file, long objID, String solrDocID, List< Long > artifactIDs, long hits, Set< BlackboardArtifact.ReviewStatus > statuses)
Optional< String > getBankCity()
Optional< String > getCardType()
final FileWithCCN fileKey
BinResult(long count, int start, int end)
void addIngestModuleEventListener(final PropertyChangeListener listener)
synchronized static Logger getLogger(String name)
static Case getCurrentCaseThrows()
final PropertyChangeListener pcl
static void addEventTypeSubscriber(Set< Events > eventTypes, PropertyChangeListener subscriber)
final AccountTypeResults accountTypeResults
boolean equals(Object obj)
static final Set< IngestManager.IngestJobEvent > INGEST_JOB_EVENTS_OF_INTEREST
ReviewStatusAction(String displayName, BlackboardArtifact.ReviewStatus newStatus)
static final String ICON_BASE_PATH
static void removeEventTypeSubscriber(Set< Events > eventTypes, PropertyChangeListener subscriber)
void actionPerformed(ActionEvent e)
String getFilterByDataSourceClause()
Optional< String > getScheme()
Optional< String > getBankName()
Optional< String > getBankPhoneNumber()
Optional< String > getCardType()