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 public Accounts(SleuthkitCase skCase,
long objId) {
139 this.filteringDSObjId = objId;
148 return visitor.
visit(
this);
159 return showRejected ?
" " :
" AND blackboard_artifacts.review_status_id != " + BlackboardArtifact.ReviewStatus.REJECTED.getID() +
" ";
169 if (filteringDSObjId > 0) {
170 return " AND blackboard_artifacts.data_source_obj_id = " + filteringDSObjId +
" ";
209 abstract protected boolean createKeys(List<X> list);
239 @NbBundle.Messages({
"Accounts.RootNode.displayName=Communication Accounts"})
250 this.setIconBaseWithExtension(
"org/sleuthkit/autopsy/images/accounts.png");
260 return visitor.
visit(
this);
265 return getClass().getName();
270 String accountTypesInUseQuery
271 =
"SELECT COUNT(*) AS count\n"
273 +
" SELECT MIN(blackboard_attributes.value_text) AS account_type\n"
274 +
" FROM blackboard_artifacts\n"
275 +
" LEFT JOIN blackboard_attributes ON blackboard_artifacts.artifact_id = blackboard_attributes.artifact_id\n"
276 +
" WHERE blackboard_artifacts.artifact_type_id = " + TSK_ACCOUNT.getTypeID() +
"\n"
277 +
" AND blackboard_attributes.attribute_type_id = " + BlackboardAttribute.Type.TSK_ACCOUNT_TYPE.getTypeID() +
"\n"
278 +
" AND blackboard_attributes.value_text IS NOT NULL\n"
280 +
" -- group by artifact_id to ensure only one account type per artifact\n"
281 +
" GROUP BY blackboard_artifacts.artifact_id\n"
284 try (SleuthkitCase.CaseDbQuery executeQuery = skCase.executeQuery(accountTypesInUseQuery);
285 ResultSet resultSet = executeQuery.getResultSet()) {
287 if (resultSet.next()) {
288 return resultSet.getLong(
"count");
291 }
catch (TskCoreException | SQLException ex) {
292 LOGGER.log(Level.SEVERE,
"Error querying for count of all account types", ex);
305 private final Map<String, Long>
counts =
new HashMap<>();
319 Long getCount(String accountType) {
320 return counts.get(accountType);
328 List<String> getTypes() {
329 List<String> types =
new ArrayList<>(counts.keySet());
330 Collections.sort(types);
338 String accountTypesInUseQuery
339 =
"SELECT res.account_type, COUNT(*) AS count\n"
341 +
" SELECT MIN(blackboard_attributes.value_text) AS account_type\n"
342 +
" FROM blackboard_artifacts\n"
343 +
" LEFT JOIN blackboard_attributes ON blackboard_artifacts.artifact_id = blackboard_attributes.artifact_id\n"
344 +
" WHERE blackboard_artifacts.artifact_type_id = " + TSK_ACCOUNT.getTypeID() +
"\n"
345 +
" AND blackboard_attributes.attribute_type_id = " + BlackboardAttribute.Type.TSK_ACCOUNT_TYPE.getTypeID() +
"\n"
347 +
" -- group by artifact_id to ensure only one account type per artifact\n"
348 +
" GROUP BY blackboard_artifacts.artifact_id\n"
350 +
"GROUP BY res.account_type";
352 try (SleuthkitCase.CaseDbQuery executeQuery = skCase.executeQuery(accountTypesInUseQuery);
353 ResultSet resultSet = executeQuery.getResultSet()) {
356 while (resultSet.next()) {
357 String accountType = resultSet.getString(
"account_type");
358 Long count = resultSet.getLong(
"count");
359 counts.put(accountType, count);
361 }
catch (TskCoreException | SQLException ex) {
362 LOGGER.log(Level.SEVERE,
"Error querying for account_types", ex);
376 private final PropertyChangeListener
pcl =
new PropertyChangeListener() {
378 public void propertyChange(PropertyChangeEvent evt) {
379 String eventType = evt.getPropertyName();
396 if (null != eventData
398 accountTypeResults.
update();
399 reviewStatusBus.post(eventData);
414 accountTypeResults.
update();
421 if (evt.getNewValue() == null) {
429 private final PropertyChangeListener
weakPcl = WeakListeners.propertyChange(pcl, null);
445 list.addAll(accountTypeResults.getTypes());
458 reviewStatusBus.register(node);
459 return new Node[]{node};
465 if (Account.Type.CREDIT_CARD.getTypeName().equals(accountTypeName)) {
470 Account.Type accountType = skCase.getCommunicationsManager().getAccountType(accountTypeName);
471 if (accountType != null) {
475 LOGGER.log(Level.SEVERE,
"Unknown account type '" + accountTypeName +
"' found - account will not be displayed.\n"
476 +
"Account type names must match an entry in the display_name column of the account_types table.\n"
477 +
"Accounts should be created using the CommunicationManager API.");
479 }
catch (TskCoreException ex) {
480 LOGGER.log(Level.SEVERE,
"Error getting display name for account type. ", ex);
514 private final PropertyChangeListener pcl =
new PropertyChangeListener() {
516 public void propertyChange(PropertyChangeEvent evt) {
517 String eventType = evt.getPropertyName();
534 if (null != eventData
536 reviewStatusBus.post(eventData);
558 if (evt.getNewValue() == null) {
566 private final PropertyChangeListener weakPcl = WeakListeners.propertyChange(pcl, null);
586 =
"SELECT blackboard_artifacts.artifact_obj_id "
587 +
" FROM blackboard_artifacts "
588 +
" JOIN blackboard_attributes ON blackboard_artifacts.artifact_id = blackboard_attributes.artifact_id "
589 +
" WHERE blackboard_artifacts.artifact_type_id = " + BlackboardArtifact.Type.TSK_ACCOUNT.getTypeID()
590 +
" AND blackboard_attributes.attribute_type_id = " + BlackboardAttribute.ATTRIBUTE_TYPE.TSK_ACCOUNT_TYPE.getTypeID()
591 +
" AND blackboard_attributes.value_text = '" + accountType.getTypeName() +
"'"
594 try (SleuthkitCase.CaseDbQuery results = skCase.executeQuery(query);
595 ResultSet rs = results.getResultSet();) {
596 List<Long> tempList =
new ArrayList<>();
598 tempList.add(rs.getLong(
"artifact_obj_id"));
600 list.addAll(tempList);
601 }
catch (TskCoreException | SQLException ex) {
602 LOGGER.log(Level.SEVERE,
"Error querying for account artifacts.", ex);
612 }
catch (TskCoreException ex) {
613 LOGGER.log(Level.SEVERE,
"Error get black board artifact with id " + t, ex);
640 super(Children.create(
new DefaultAccountFactory(accountType),
true), Lookups.singleton(accountType));
643 this.setIconBaseWithExtension(iconPath != null && iconPath.charAt(0) ==
'/' ? iconPath.substring(1) : iconPath);
644 setName(accountType.getTypeName());
655 return visitor.
visit(
this);
660 return getClass().getName();
678 setDisplayName(String.format(
"%s (%d)", accountType.getDisplayName(), accountTypeResults.getCount(accountType.getTypeName())));
692 private final PropertyChangeListener pcl =
new PropertyChangeListener() {
694 public void propertyChange(PropertyChangeEvent evt) {
695 String eventType = evt.getPropertyName();
712 if (null != eventData
714 reviewStatusBus.post(eventData);
736 if (evt.getNewValue() == null) {
744 private final PropertyChangeListener weakPcl = WeakListeners.propertyChange(pcl, null);
772 super.removeNotify();
779 protected boolean createKeys(List<CreditCardViewMode> list) {
808 super(Children.create(
new ViewModeFactory(),
true), Lookups.singleton(Account.Type.CREDIT_CARD.getDisplayName()));
809 setName(Account.Type.CREDIT_CARD.getDisplayName());
810 this.setIconBaseWithExtension(
"org/sleuthkit/autopsy/images/credit-cards.png");
818 setName(String.format(
"%s (%d)", Account.Type.CREDIT_CARD.getDisplayName(), accountTypeResults.getCount(Account.Type.CREDIT_CARD.getTypeName())));
838 return visitor.
visit(
this);
843 return getClass().getName();
849 private final PropertyChangeListener pcl =
new PropertyChangeListener() {
851 public void propertyChange(PropertyChangeEvent evt) {
852 String eventType = evt.getPropertyName();
869 if (null != eventData
871 reviewStatusBus.post(eventData);
893 if (evt.getNewValue() == null) {
901 private final PropertyChangeListener weakPcl = WeakListeners.propertyChange(pcl, null);
934 =
"SELECT blackboard_artifacts.obj_id,"
935 +
" solr_attribute.value_text AS solr_document_id, ";
936 if (skCase.getDatabaseType().equals(DbType.POSTGRESQL)) {
937 query +=
" string_agg(blackboard_artifacts.artifact_id::character varying, ',') AS artifact_IDs, "
938 +
" string_agg(blackboard_artifacts.review_status_id::character varying, ',') AS review_status_ids, ";
940 query +=
" GROUP_CONCAT(blackboard_artifacts.artifact_id) AS artifact_IDs, "
941 +
" GROUP_CONCAT(blackboard_artifacts.review_status_id) AS review_status_ids, ";
943 query +=
" COUNT( blackboard_artifacts.artifact_id) AS hits "
944 +
" FROM blackboard_artifacts "
945 +
" LEFT JOIN blackboard_attributes as solr_attribute ON blackboard_artifacts.artifact_id = solr_attribute.artifact_id "
946 +
" AND solr_attribute.attribute_type_id = " + BlackboardAttribute.ATTRIBUTE_TYPE.TSK_KEYWORD_SEARCH_DOCUMENT_ID.getTypeID()
947 +
" LEFT JOIN blackboard_attributes as account_type ON blackboard_artifacts.artifact_id = account_type.artifact_id "
948 +
" AND account_type.attribute_type_id = " + BlackboardAttribute.ATTRIBUTE_TYPE.TSK_ACCOUNT_TYPE.getTypeID()
949 +
" AND account_type.value_text = '" + Account.Type.CREDIT_CARD.getTypeName() +
"'"
950 +
" WHERE blackboard_artifacts.artifact_type_id = " + BlackboardArtifact.Type.TSK_ACCOUNT.getTypeID()
953 +
" GROUP BY blackboard_artifacts.obj_id, solr_document_id "
954 +
" ORDER BY hits DESC ";
955 try (SleuthkitCase.CaseDbQuery results = skCase.executeQuery(query);
956 ResultSet resultSet = results.getResultSet();) {
957 while (resultSet.next()) {
958 long file_id = resultSet.getLong(
"obj_id");
959 AbstractFile abstractFileById = skCase.getAbstractFileById(file_id);
960 if(abstractFileById != null) {
964 resultSet.getString(
"solr_document_id"),
965 unGroupConcat(resultSet.getString(
"artifact_IDs"), Long::valueOf),
966 resultSet.getLong(
"hits"),
967 new HashSet<>(unGroupConcat(resultSet.getString(
"review_status_ids"), reviewStatusID -> BlackboardArtifact.ReviewStatus.withID(Integer.valueOf(reviewStatusID))))));
970 }
catch (TskCoreException | SQLException ex) {
971 LOGGER.log(Level.SEVERE,
"Error querying for files with ccn hits.", ex);
981 List<Object> lookupContents =
new ArrayList<>();
983 lookupContents.add(skCase.getBlackboardArtifact(artId));
985 AbstractFile abstractFileById = key.getFile();
986 lookupContents.add(abstractFileById);
987 return new Node[]{
new FileWithCCNNode(key, abstractFileById, lookupContents.toArray())};
988 }
catch (TskCoreException ex) {
989 LOGGER.log(Level.SEVERE,
"Error getting content for file with ccn hits.", ex);
1005 super(Children.create(
new FileWithCCNFactory(),
true), Lookups.singleton(
"By File"));
1007 updateDisplayName();
1008 this.setIconBaseWithExtension(
"org/sleuthkit/autopsy/images/file-icon.png");
1009 reviewStatusBus.register(
this);
1012 @NbBundle.Messages({
1013 "# {0} - number of children",
1014 "Accounts.ByFileNode.displayName=By File ({0})"})
1017 =
"SELECT count(*) FROM ( SELECT count(*) AS documents "
1018 +
" FROM blackboard_artifacts "
1019 +
" LEFT JOIN blackboard_attributes as solr_attribute ON blackboard_artifacts.artifact_id = solr_attribute.artifact_id "
1020 +
" AND solr_attribute.attribute_type_id = " + BlackboardAttribute.ATTRIBUTE_TYPE.TSK_KEYWORD_SEARCH_DOCUMENT_ID.getTypeID()
1021 +
" LEFT JOIN blackboard_attributes as account_type ON blackboard_artifacts.artifact_id = account_type.artifact_id "
1022 +
" AND account_type.attribute_type_id = " + BlackboardAttribute.ATTRIBUTE_TYPE.TSK_ACCOUNT_TYPE.getTypeID()
1023 +
" AND account_type.value_text = '" + Account.Type.CREDIT_CARD.getTypeName() +
"'"
1024 +
" WHERE blackboard_artifacts.artifact_type_id = " + BlackboardArtifact.Type.TSK_ACCOUNT.getTypeID()
1027 +
" GROUP BY blackboard_artifacts.obj_id, solr_attribute.value_text ) AS foo";
1028 try (SleuthkitCase.CaseDbQuery results = skCase.executeQuery(query);
1029 ResultSet resultSet = results.getResultSet();) {
1030 while (resultSet.next()) {
1031 if (skCase.getDatabaseType().equals(DbType.POSTGRESQL)) {
1032 setDisplayName(Bundle.Accounts_ByFileNode_displayName(resultSet.getLong(
"count")));
1034 setDisplayName(Bundle.Accounts_ByFileNode_displayName(resultSet.getLong(
"count(*)")));
1037 }
catch (TskCoreException | SQLException ex) {
1038 LOGGER.log(Level.SEVERE,
"Error querying for files with ccn hits.", ex);
1050 return visitor.
visit(
this);
1055 return getClass().getName();
1060 updateDisplayName();
1065 updateDisplayName();
1071 private final PropertyChangeListener pcl =
new PropertyChangeListener() {
1073 public void propertyChange(PropertyChangeEvent evt) {
1074 String eventType = evt.getPropertyName();
1091 if (null != eventData
1093 reviewStatusBus.post(eventData);
1114 && (evt.getNewValue() == null)) {
1122 private final PropertyChangeListener weakPcl = WeakListeners.propertyChange(pcl, null);
1155 RangeMap<Integer, BinResult> binRanges = TreeRangeMap.create();
1158 =
"SELECT SUBSTR(blackboard_attributes.value_text,1,8) AS BIN, "
1159 +
" COUNT(blackboard_artifacts.artifact_id) AS count "
1160 +
" FROM blackboard_artifacts "
1161 +
" JOIN blackboard_attributes ON blackboard_artifacts.artifact_id = blackboard_attributes.artifact_id"
1162 +
" WHERE blackboard_artifacts.artifact_type_id = " + BlackboardArtifact.Type.TSK_ACCOUNT.getTypeID()
1163 +
" AND blackboard_attributes.attribute_type_id = " + BlackboardAttribute.ATTRIBUTE_TYPE.TSK_CARD_NUMBER.getTypeID()
1168 try (SleuthkitCase.CaseDbQuery results = skCase.executeQuery(query);
1169 ResultSet resultSet = results.getResultSet();) {
1171 while (resultSet.next()) {
1172 final Integer bin = Integer.valueOf(resultSet.getString(
"BIN"));
1173 long count = resultSet.getLong(
"count");
1176 BinResult previousResult = binRanges.get(bin);
1178 if (previousResult != null) {
1179 binRanges.remove(Range.closed(previousResult.getBINStart(), previousResult.getBINEnd()));
1180 count += previousResult.getCount();
1183 if (binRange == null) {
1184 binRanges.put(Range.closed(bin, bin),
new BinResult(count, bin, bin));
1189 binRanges.asMapOfRanges().values().forEach(list::add);
1190 }
catch (TskCoreException | SQLException ex) {
1191 LOGGER.log(Level.SEVERE,
"Error querying for BINs.", ex);
1199 return new Node[]{
new BINNode(key)};
1212 @NbBundle.Messages(
"Accounts.ByBINNode.name=By BIN")
1214 super(Children.create(
new BINFactory(),
true), Lookups.singleton(Bundle.Accounts_ByBINNode_name()));
1215 setName(Bundle.Accounts_ByBINNode_name());
1216 updateDisplayName();
1217 this.setIconBaseWithExtension(
"org/sleuthkit/autopsy/images/bank.png");
1218 reviewStatusBus.register(
this);
1221 @NbBundle.Messages({
1222 "# {0} - number of children",
1223 "Accounts.ByBINNode.displayName=By BIN ({0})"})
1226 =
"SELECT count(distinct SUBSTR(blackboard_attributes.value_text,1,8)) AS BINs "
1227 +
" FROM blackboard_artifacts "
1228 +
" JOIN blackboard_attributes ON blackboard_artifacts.artifact_id = blackboard_attributes.artifact_id"
1229 +
" WHERE blackboard_artifacts.artifact_type_id = " + BlackboardArtifact.Type.TSK_ACCOUNT.getTypeID()
1230 +
" AND blackboard_attributes.attribute_type_id = " + BlackboardAttribute.ATTRIBUTE_TYPE.TSK_CARD_NUMBER.getTypeID()
1233 try (SleuthkitCase.CaseDbQuery results = skCase.executeQuery(query);
1234 ResultSet resultSet = results.getResultSet();) {
1235 while (resultSet.next()) {
1236 setDisplayName(Bundle.Accounts_ByBINNode_displayName(resultSet.getLong(
"BINs")));
1238 }
catch (TskCoreException | SQLException ex) {
1239 LOGGER.log(Level.SEVERE,
"Error querying for BINs.", ex);
1250 return visitor.
visit(
this);
1255 return getClass().getName();
1260 updateDisplayName();
1265 updateDisplayName();
1279 hash = 79 * hash + (int) (this.objID ^ (this.objID >>> 32));
1280 hash = 79 * hash + Objects.hashCode(this.keywordSearchDocID);
1281 hash = 79 * hash + Objects.hashCode(this.artifactIDs);
1282 hash = 79 * hash + (int) (this.hits ^ (this.hits >>> 32));
1283 hash = 79 * hash + Objects.hashCode(this.statuses);
1295 if (getClass() != obj.getClass()) {
1299 if (this.objID != other.
objID) {
1302 if (this.hits != other.
hits) {
1308 if (!Objects.equals(
this.artifactIDs, other.
artifactIDs)) {
1311 if (!Objects.equals(
this.statuses, other.
statuses)) {
1321 private final Set<BlackboardArtifact.ReviewStatus>
statuses;
1324 private FileWithCCN(AbstractFile file,
long objID, String solrDocID, List<Long> artifactIDs,
long hits, Set<BlackboardArtifact.ReviewStatus> statuses) {
1326 this.keywordSearchDocID = solrDocID;
1327 this.artifactIDs = artifactIDs;
1329 this.statuses = statuses;
1349 return keywordSearchDocID;
1358 return Collections.unmodifiableList(artifactIDs);
1376 return Collections.unmodifiableSet(statuses);
1379 AbstractFile getFile() {
1400 static <X> List<X> unGroupConcat(String groupConcat, Function<String, X> mapper) {
1401 return StringUtils.isBlank(groupConcat) ? Collections.emptyList()
1402 : Stream.of(groupConcat.split(
","))
1404 .collect(Collectors.toList());
1424 @NbBundle.Messages({
1425 "# {0} - raw file name",
1426 "# {1} - solr chunk id",
1427 "Accounts.FileWithCCNNode.unallocatedSpaceFile.displayName={0}_chunk_{1}"})
1429 super(Children.LEAF, Lookups.fixed(lookupContents));
1433 : Bundle.Accounts_FileWithCCNNode_unallocatedSpaceFile_displayName(content.getName(), StringUtils.substringAfter(key.
getkeywordSearchDocID(),
"_"));
1434 setName(fileName + key.
getObjID());
1435 setDisplayName(fileName);
1445 return visitor.
visit(
this);
1450 return getClass().getName();
1454 @NbBundle.Messages({
1455 "Accounts.FileWithCCNNode.nameProperty.displayName=File",
1456 "Accounts.FileWithCCNNode.accountsProperty.displayName=Accounts",
1457 "Accounts.FileWithCCNNode.statusProperty.displayName=Status",
1458 "Accounts.FileWithCCNNode.noDescription=no description"})
1460 Sheet sheet = super.createSheet();
1461 Sheet.Set propSet = sheet.get(Sheet.PROPERTIES);
1462 if (propSet == null) {
1463 propSet = Sheet.createPropertiesSet();
1467 propSet.put(
new NodeProperty<>(Bundle.Accounts_FileWithCCNNode_nameProperty_displayName(),
1468 Bundle.Accounts_FileWithCCNNode_nameProperty_displayName(),
1469 Bundle.Accounts_FileWithCCNNode_noDescription(),
1471 propSet.put(
new NodeProperty<>(Bundle.Accounts_FileWithCCNNode_accountsProperty_displayName(),
1472 Bundle.Accounts_FileWithCCNNode_accountsProperty_displayName(),
1473 Bundle.Accounts_FileWithCCNNode_noDescription(),
1475 propSet.put(
new NodeProperty<>(Bundle.Accounts_FileWithCCNNode_statusProperty_displayName(),
1476 Bundle.Accounts_FileWithCCNNode_statusProperty_displayName(),
1477 Bundle.Accounts_FileWithCCNNode_noDescription(),
1479 .map(BlackboardArtifact.ReviewStatus::getDisplayName)
1480 .collect(Collectors.joining(
", "))));
1487 Action[] actions = super.getActions(context);
1488 ArrayList<Action> arrayList =
new ArrayList<>();
1491 }
catch (TskCoreException ex) {
1492 LOGGER.log(Level.SEVERE,
"Error gettung content by id", ex);
1495 arrayList.add(approveActionInstance);
1496 arrayList.add(rejectActionInstance);
1497 arrayList.add(null);
1498 arrayList.addAll(Arrays.asList(actions));
1499 return arrayList.toArray(
new Action[arrayList.size()]);
1527 =
"SELECT blackboard_artifacts.artifact_obj_id "
1528 +
" FROM blackboard_artifacts "
1529 +
" JOIN blackboard_attributes ON blackboard_artifacts.artifact_id = blackboard_attributes.artifact_id "
1530 +
" WHERE blackboard_artifacts.artifact_type_id = " + BlackboardArtifact.Type.TSK_ACCOUNT.getTypeID()
1531 +
" AND blackboard_attributes.attribute_type_id = " + BlackboardAttribute.ATTRIBUTE_TYPE.TSK_CARD_NUMBER.getTypeID()
1532 +
" AND blackboard_attributes.value_text >= '" + bin.getBINStart() +
"' AND blackboard_attributes.value_text < '" + (bin.getBINEnd() + 1) +
"'"
1535 +
" ORDER BY blackboard_attributes.value_text";
1536 try (SleuthkitCase.CaseDbQuery results = skCase.executeQuery(query);
1537 ResultSet rs = results.getResultSet();) {
1539 list.add(skCase.getBlackboard().getDataArtifactById(rs.getLong(
"artifact_obj_id")));
1541 }
catch (TskCoreException | SQLException ex) {
1542 LOGGER.log(Level.SEVERE,
"Error querying for account artifacts.", ex);
1555 if (bin.getBINStart() == bin.getBINEnd()) {
1556 return Integer.toString(bin.getBINStart());
1558 return bin.getBINStart() +
"-" + StringUtils.difference(bin.getBINStart() +
"", bin.getBINEnd() +
"");
1573 updateDisplayName();
1574 this.setIconBaseWithExtension(
"org/sleuthkit/autopsy/images/bank.png");
1575 reviewStatusBus.register(
this);
1580 updateDisplayName();
1586 updateDisplayName();
1591 =
"SELECT count(blackboard_artifacts.artifact_id ) AS count"
1592 +
" FROM blackboard_artifacts "
1593 +
" JOIN blackboard_attributes ON blackboard_artifacts.artifact_id = blackboard_attributes.artifact_id "
1594 +
" WHERE blackboard_artifacts.artifact_type_id = " + BlackboardArtifact.Type.TSK_ACCOUNT.getTypeID()
1595 +
" AND blackboard_attributes.attribute_type_id = " + BlackboardAttribute.ATTRIBUTE_TYPE.TSK_CARD_NUMBER.getTypeID()
1596 +
" AND blackboard_attributes.value_text >= '" + bin.getBINStart() +
"' AND blackboard_attributes.value_text < '" + (bin.getBINEnd() + 1) +
"'"
1599 try (SleuthkitCase.CaseDbQuery results = skCase.executeQuery(query);
1600 ResultSet resultSet = results.getResultSet();) {
1601 while (resultSet.next()) {
1602 setDisplayName(
getBinRangeString(bin) +
" (" + resultSet.getLong(
"count") +
")");
1604 }
catch (TskCoreException | SQLException ex) {
1605 LOGGER.log(Level.SEVERE,
"Error querying for account artifacts.", ex);
1618 return visitor.
visit(
this);
1623 return getClass().getName();
1627 Sheet.Set sheetSet = sheet.get(Sheet.PROPERTIES);
1628 if (sheetSet == null) {
1629 sheetSet = Sheet.createPropertiesSet();
1630 sheet.put(sheetSet);
1636 @NbBundle.Messages({
1637 "Accounts.BINNode.binProperty.displayName=Bank Identifier Number",
1638 "Accounts.BINNode.accountsProperty.displayName=Accounts",
1639 "Accounts.BINNode.cardTypeProperty.displayName=Payment Card Type",
1640 "Accounts.BINNode.schemeProperty.displayName=Credit Card Scheme",
1641 "Accounts.BINNode.brandProperty.displayName=Brand",
1642 "Accounts.BINNode.bankProperty.displayName=Bank",
1643 "Accounts.BINNode.bankCityProperty.displayName=Bank City",
1644 "Accounts.BINNode.bankCountryProperty.displayName=Bank Country",
1645 "Accounts.BINNode.bankPhoneProperty.displayName=Bank Phone #",
1646 "Accounts.BINNode.bankURLProperty.displayName=Bank URL",
1647 "Accounts.BINNode.noDescription=no description"})
1649 Sheet sheet = super.createSheet();
1650 Sheet.Set properties = getPropertySet(sheet);
1652 properties.put(
new NodeProperty<>(Bundle.Accounts_BINNode_binProperty_displayName(),
1653 Bundle.Accounts_BINNode_binProperty_displayName(),
1654 Bundle.Accounts_BINNode_noDescription(),
1656 properties.put(
new NodeProperty<>(Bundle.Accounts_BINNode_accountsProperty_displayName(),
1657 Bundle.Accounts_BINNode_accountsProperty_displayName(), Bundle.Accounts_BINNode_noDescription(),
1661 if (bin.hasDetails()) {
1662 bin.
getCardType().ifPresent(cardType -> properties.put(
new NodeProperty<>(Bundle.Accounts_BINNode_cardTypeProperty_displayName(),
1663 Bundle.Accounts_BINNode_cardTypeProperty_displayName(), Bundle.Accounts_BINNode_noDescription(),
1665 bin.
getScheme().ifPresent(scheme -> properties.put(
new NodeProperty<>(Bundle.Accounts_BINNode_schemeProperty_displayName(),
1666 Bundle.Accounts_BINNode_schemeProperty_displayName(), Bundle.Accounts_BINNode_noDescription(),
1668 bin.
getBrand().ifPresent(brand -> properties.put(
new NodeProperty<>(Bundle.Accounts_BINNode_brandProperty_displayName(),
1669 Bundle.Accounts_BINNode_brandProperty_displayName(), Bundle.Accounts_BINNode_noDescription(),
1671 bin.
getBankName().ifPresent(bankName -> properties.put(
new NodeProperty<>(Bundle.Accounts_BINNode_bankProperty_displayName(),
1672 Bundle.Accounts_BINNode_bankProperty_displayName(), Bundle.Accounts_BINNode_noDescription(),
1674 bin.
getBankCity().ifPresent(bankCity -> properties.put(
new NodeProperty<>(Bundle.Accounts_BINNode_bankCityProperty_displayName(),
1675 Bundle.Accounts_BINNode_bankCityProperty_displayName(), Bundle.Accounts_BINNode_noDescription(),
1677 bin.
getCountry().ifPresent(country -> properties.put(
new NodeProperty<>(Bundle.Accounts_BINNode_bankCountryProperty_displayName(),
1678 Bundle.Accounts_BINNode_bankCountryProperty_displayName(), Bundle.Accounts_BINNode_noDescription(),
1681 Bundle.Accounts_BINNode_bankPhoneProperty_displayName(), Bundle.Accounts_BINNode_noDescription(),
1683 bin.
getBankURL().ifPresent(url -> properties.put(
new NodeProperty<>(Bundle.Accounts_BINNode_bankURLProperty_displayName(),
1684 Bundle.Accounts_BINNode_bankURLProperty_displayName(), Bundle.Accounts_BINNode_noDescription(),
1691 SwingUtilities.invokeLater(() -> {
1692 this.setSheet(createSheet());
1708 hash = 97 * hash + this.binEnd;
1709 hash = 97 * hash + this.binStart;
1721 if (getClass() != obj.getClass()) {
1725 if (this.binEnd != other.
binEnd) {
1728 if (this.binStart != other.
binStart) {
1745 this.binRange = binRange;
1746 binStart = binRange.getBINstart();
1747 binEnd = binRange.getBINend();
1752 this.binRange = null;
1769 boolean hasDetails() {
1770 return binRange != null;
1824 super(artifact,
"org/sleuthkit/autopsy/images/credit-card.png");
1825 this.artifact = artifact;
1826 setName(Long.toString(
this.artifact.getArtifactID()));
1828 reviewStatusBus.register(
this);
1833 List<Action> actionsList =
new ArrayList<>();
1834 actionsList.addAll(Arrays.asList(super.getActions(context)));
1836 actionsList.add(approveActionInstance);
1837 actionsList.add(rejectActionInstance);
1839 return actionsList.toArray(
new Action[actionsList.size()]);
1844 Sheet sheet = super.createSheet();
1845 Sheet.Set properties = sheet.get(Sheet.PROPERTIES);
1846 if (properties == null) {
1847 properties = Sheet.createPropertiesSet();
1848 sheet.put(properties);
1850 properties.put(
new NodeProperty<>(Bundle.Accounts_FileWithCCNNode_statusProperty_displayName(),
1851 Bundle.Accounts_FileWithCCNNode_statusProperty_displayName(),
1852 Bundle.Accounts_FileWithCCNNode_noDescription(),
1853 artifact.getReviewStatus().getDisplayName()));
1862 event.artifacts.stream().filter((art) -> (art.getArtifactID() == this.artifact.getArtifactID())).map((_item) -> {
1864 }).forEachOrdered((_item) -> {
1870 SwingUtilities.invokeLater(() -> {
1871 this.setSheet(createSheet());
1880 @NbBundle.Messages(
"ToggleShowRejected.name=Show Rejected Results")
1882 super(Bundle.ToggleShowRejected_name());
1908 this.newStatus = newStatus;
1919 List<String[]> selectedPaths = Utilities.actionsGlobalContext().lookupAll(Node.class).stream()
1921 String[] createPath;
1927 if (newStatus == BlackboardArtifact.ReviewStatus.REJECTED && showRejected ==
false) {
1928 List<Node> siblings = Arrays.asList(node.getParentNode().getChildren().getNodes());
1929 if (siblings.size() > 1) {
1930 int indexOf = siblings.indexOf(node);
1932 Node sibling = indexOf > 0
1933 ? siblings.get(indexOf - 1)
1934 : siblings.get(Integer.max(indexOf + 1, siblings.size() - 1));
1935 createPath = NodeOp.createPath(sibling, null);
1945 createPath = NodeOp.createPath(node, null);
1948 return Arrays.copyOfRange(createPath, 1, createPath.length);
1950 .filter(Objects::nonNull)
1951 .collect(Collectors.toList());
1954 final Collection<? extends BlackboardArtifact> artifacts = Utilities.actionsGlobalContext().lookupAll(BlackboardArtifact.class);
1955 artifacts.forEach(artifact -> {
1957 artifact.setReviewStatus(newStatus);
1958 }
catch (TskCoreException ex) {
1959 LOGGER.log(Level.SEVERE,
"Error changing artifact review status.", ex);
1963 reviewStatusBus.post(
new ReviewStatusChangeEvent(artifacts, newStatus));
1965 final DataResultTopComponent directoryListing = DirectoryTreeTopComponent.findInstance().getDirectoryListing();
1966 final Node rootNode = directoryListing.getRootNode();
1969 List<Node> toArray =
new ArrayList<>();
1970 selectedPaths.forEach(path -> {
1972 toArray.add(NodeOp.findPath(rootNode, path));
1973 }
catch (NodeNotFoundException ex) {
1978 directoryListing.setSelectedNodes(toArray.toArray(
new Node[toArray.size()]));
1984 @NbBundle.Messages({
"ApproveAccountsAction.name=Approve Accounts"})
1986 super(Bundle.ApproveAccountsAction_name(), BlackboardArtifact.ReviewStatus.APPROVED);
1992 @NbBundle.Messages({
"RejectAccountsAction.name=Reject Accounts"})
1994 super(Bundle.RejectAccountsAction_name(), BlackboardArtifact.ReviewStatus.REJECTED);
2000 Collection<? extends BlackboardArtifact> artifacts;
2001 BlackboardArtifact.ReviewStatus newReviewStatus;
2003 ReviewStatusChangeEvent(Collection<? extends BlackboardArtifact> artifacts, BlackboardArtifact.ReviewStatus newReviewStatus) {
2004 this.artifacts = artifacts;
2005 this.newReviewStatus = newReviewStatus;
2016 if (type.equals(Account.Type.CREDIT_CARD)) {
2017 return ICON_BASE_PATH +
"credit-card.png";
2018 }
else if (type.equals(Account.Type.DEVICE)) {
2019 return ICON_BASE_PATH +
"image.png";
2020 }
else if (type.equals(Account.Type.EMAIL)) {
2021 return ICON_BASE_PATH +
"email.png";
2022 }
else if (type.equals(Account.Type.FACEBOOK)) {
2023 return ICON_BASE_PATH +
"facebook.png";
2024 }
else if (type.equals(Account.Type.INSTAGRAM)) {
2025 return ICON_BASE_PATH +
"instagram.png";
2026 }
else if (type.equals(Account.Type.MESSAGING_APP)) {
2027 return ICON_BASE_PATH +
"messaging.png";
2028 }
else if (type.equals(Account.Type.PHONE)) {
2029 return ICON_BASE_PATH +
"phone.png";
2030 }
else if (type.equals(Account.Type.TWITTER)) {
2031 return ICON_BASE_PATH +
"twitter.png";
2032 }
else if (type.equals(Account.Type.WEBSITE)) {
2033 return ICON_BASE_PATH +
"web-file.png";
2034 }
else if (type.equals(Account.Type.WHATSAPP)) {
2035 return ICON_BASE_PATH +
"WhatsApp.png";
2038 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()
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)
Accounts(SleuthkitCase skCase, long objId)
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()
Accounts(SleuthkitCase skCase)