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 org.apache.commons.lang3.StringUtils;
52 import org.openide.nodes.ChildFactory;
53 import org.openide.nodes.Children;
54 import org.openide.nodes.Node;
55 import org.openide.nodes.NodeNotFoundException;
56 import org.openide.nodes.NodeOp;
57 import org.openide.nodes.Sheet;
58 import org.openide.util.NbBundle;
59 import org.openide.util.Utilities;
60 import org.openide.util.WeakListeners;
61 import org.openide.util.lookup.Lookups;
82 import static org.
sleuthkit.datamodel.BlackboardArtifact.Type.TSK_ACCOUNT;
97 private static final String
ICON_BASE_PATH =
"/org/sleuthkit/autopsy/images/";
100 private static final String
DISPLAY_NAME = Bundle.Accounts_RootNode_displayName();
102 @NbBundle.Messages(
"AccountsRootNode.name=Accounts")
103 final public static String
NAME = Bundle.AccountsRootNode_name();
136 public Accounts(SleuthkitCase skCase,
long objId) {
138 this.filteringDSObjId = objId;
147 return visitor.
visit(
this);
158 return showRejected ?
" " :
" AND blackboard_artifacts.review_status_id != " + BlackboardArtifact.ReviewStatus.REJECTED.getID() +
" ";
168 if (filteringDSObjId > 0) {
169 return " AND blackboard_artifacts.data_source_obj_id = " + filteringDSObjId +
" ";
208 abstract protected boolean createKeys(List<X> list);
238 @NbBundle.Messages({
"Accounts.RootNode.displayName=Communication Accounts"})
249 this.setIconBaseWithExtension(
"org/sleuthkit/autopsy/images/accounts.png");
259 return visitor.
visit(
this);
264 return getClass().getName();
270 String dataSourceFilterClause = (filteringDSObjId > 0)
271 ?
" AND " + filteringDSObjId +
" IN (SELECT art.data_source_obj_id FROM blackboard_artifacts art WHERE art.artifact_id = attr.artifact_id)"
274 String accountTypesInUseQuery
275 =
"SELECT COUNT(attr.value_text) AS count"
276 +
" FROM blackboard_attributes attr"
277 +
" WHERE attr.attribute_type_id = " + BlackboardAttribute.ATTRIBUTE_TYPE.TSK_ACCOUNT_TYPE.getTypeID()
278 +
" AND attr.artifact_type_id = " + BlackboardArtifact.Type.TSK_ACCOUNT.getTypeID()
279 + dataSourceFilterClause
280 +
" GROUP BY attr.value_text";
282 try (SleuthkitCase.CaseDbQuery executeQuery = skCase.executeQuery(accountTypesInUseQuery);
283 ResultSet resultSet = executeQuery.getResultSet()) {
285 if (resultSet.next()) {
286 count = resultSet.getLong(
"count");
289 }
catch (TskCoreException | SQLException ex) {
290 LOGGER.log(Level.SEVERE,
"Error querying for count of all account types", ex);
302 private final Map<String, Long>
counts =
new HashMap<>();
316 Long getCount(String accountType) {
317 return counts.get(accountType);
325 List<String> getTypes() {
326 List<String> types =
new ArrayList<>(counts.keySet());
327 Collections.sort(types);
335 String accountTypesInUseQuery
336 =
"SELECT blackboard_attributes.value_text as account_type, COUNT(*) as count "
337 +
" FROM blackboard_artifacts "
338 +
" JOIN blackboard_attributes ON blackboard_artifacts.artifact_id = blackboard_attributes.artifact_id "
339 +
" WHERE blackboard_artifacts.artifact_type_id = " + TSK_ACCOUNT.getTypeID()
340 +
" AND blackboard_attributes.attribute_type_id = " + BlackboardAttribute.ATTRIBUTE_TYPE.TSK_ACCOUNT_TYPE.getTypeID()
342 +
" GROUP BY blackboard_attributes.value_text ";
344 try (SleuthkitCase.CaseDbQuery executeQuery = skCase.executeQuery(accountTypesInUseQuery);
345 ResultSet resultSet = executeQuery.getResultSet()) {
348 while (resultSet.next()) {
349 String accountType = resultSet.getString(
"account_type");
350 Long count = resultSet.getLong(
"count");
351 counts.put(accountType, count);
353 }
catch (TskCoreException | SQLException ex) {
354 LOGGER.log(Level.SEVERE,
"Error querying for account_types", ex);
368 private final PropertyChangeListener
pcl =
new PropertyChangeListener() {
370 public void propertyChange(PropertyChangeEvent evt) {
371 String eventType = evt.getPropertyName();
388 if (null != eventData
390 accountTypeResults.
update();
391 reviewStatusBus.post(eventData);
412 if (evt.getNewValue() == null) {
420 private final PropertyChangeListener
weakPcl = WeakListeners.propertyChange(pcl, null);
436 list.addAll(accountTypeResults.getTypes());
449 reviewStatusBus.register(node);
450 return new Node[]{node};
456 if (Account.Type.CREDIT_CARD.getTypeName().equals(accountTypeName)) {
461 Account.Type accountType = skCase.getCommunicationsManager().getAccountType(accountTypeName);
462 if (accountType != null) {
466 LOGGER.log(Level.SEVERE,
"Unknown account type '" + accountTypeName +
"' found - account will not be displayed.\n"
467 +
"Account type names must match an entry in the display_name column of the account_types table.\n"
468 +
"Accounts should be created using the CommunicationManager API.");
470 }
catch (TskCoreException ex) {
471 LOGGER.log(Level.SEVERE,
"Error getting display name for account type. ", ex);
505 private final PropertyChangeListener pcl =
new PropertyChangeListener() {
507 public void propertyChange(PropertyChangeEvent evt) {
508 String eventType = evt.getPropertyName();
525 if (null != eventData
527 reviewStatusBus.post(eventData);
549 if (evt.getNewValue() == null) {
557 private final PropertyChangeListener weakPcl = WeakListeners.propertyChange(pcl, null);
577 =
"SELECT blackboard_artifacts.artifact_obj_id "
578 +
" FROM blackboard_artifacts "
579 +
" JOIN blackboard_attributes ON blackboard_artifacts.artifact_id = blackboard_attributes.artifact_id "
580 +
" WHERE blackboard_artifacts.artifact_type_id = " + BlackboardArtifact.Type.TSK_ACCOUNT.getTypeID()
581 +
" AND blackboard_attributes.attribute_type_id = " + BlackboardAttribute.ATTRIBUTE_TYPE.TSK_ACCOUNT_TYPE.getTypeID()
582 +
" AND blackboard_attributes.value_text = '" + accountType.getTypeName() +
"'"
585 try (SleuthkitCase.CaseDbQuery results = skCase.executeQuery(query);
586 ResultSet rs = results.getResultSet();) {
587 List<Long> tempList =
new ArrayList<>();
589 tempList.add(rs.getLong(
"artifact_obj_id"));
591 list.addAll(tempList);
592 }
catch (TskCoreException | SQLException ex) {
593 LOGGER.log(Level.SEVERE,
"Error querying for account artifacts.", ex);
603 }
catch (TskCoreException ex) {
604 LOGGER.log(Level.SEVERE,
"Error get black board artifact with id " + t, ex);
631 super(Children.create(
new DefaultAccountFactory(accountType),
true), Lookups.singleton(accountType));
634 this.setIconBaseWithExtension(iconPath != null && iconPath.charAt(0) ==
'/' ? iconPath.substring(1) : iconPath);
635 setName(accountType.getTypeName());
646 return visitor.
visit(
this);
651 return getClass().getName();
669 setDisplayName(String.format(
"%s (%d)", accountType.getDisplayName(), accountTypeResults.getCount(accountType.getTypeName())));
683 private final PropertyChangeListener pcl =
new PropertyChangeListener() {
685 public void propertyChange(PropertyChangeEvent evt) {
686 String eventType = evt.getPropertyName();
703 if (null != eventData
705 reviewStatusBus.post(eventData);
727 if (evt.getNewValue() == null) {
735 private final PropertyChangeListener weakPcl = WeakListeners.propertyChange(pcl, null);
764 super.removeNotify();
771 protected boolean createKeys(List<CreditCardViewMode> list) {
800 super(Children.create(
new ViewModeFactory(),
true), Lookups.singleton(Account.Type.CREDIT_CARD.getDisplayName()));
801 setName(Account.Type.CREDIT_CARD.getDisplayName());
802 this.setIconBaseWithExtension(
"org/sleuthkit/autopsy/images/credit-cards.png");
810 setName(String.format(
"%s (%d)", Account.Type.CREDIT_CARD.getDisplayName(), accountTypeResults.getCount(Account.Type.CREDIT_CARD.getTypeName())));
830 return visitor.
visit(
this);
835 return getClass().getName();
841 private final PropertyChangeListener pcl =
new PropertyChangeListener() {
843 public void propertyChange(PropertyChangeEvent evt) {
844 String eventType = evt.getPropertyName();
861 if (null != eventData
863 reviewStatusBus.post(eventData);
885 if (evt.getNewValue() == null) {
893 private final PropertyChangeListener weakPcl = WeakListeners.propertyChange(pcl, null);
926 =
"SELECT blackboard_artifacts.obj_id,"
927 +
" solr_attribute.value_text AS solr_document_id, ";
928 if (skCase.getDatabaseType().equals(DbType.POSTGRESQL)) {
929 query +=
" string_agg(blackboard_artifacts.artifact_id::character varying, ',') AS artifact_IDs, "
930 +
" string_agg(blackboard_artifacts.review_status_id::character varying, ',') AS review_status_ids, ";
932 query +=
" GROUP_CONCAT(blackboard_artifacts.artifact_id) AS artifact_IDs, "
933 +
" GROUP_CONCAT(blackboard_artifacts.review_status_id) AS review_status_ids, ";
935 query +=
" COUNT( blackboard_artifacts.artifact_id) AS hits "
936 +
" FROM blackboard_artifacts "
937 +
" LEFT JOIN blackboard_attributes as solr_attribute ON blackboard_artifacts.artifact_id = solr_attribute.artifact_id "
938 +
" AND solr_attribute.attribute_type_id = " + BlackboardAttribute.ATTRIBUTE_TYPE.TSK_KEYWORD_SEARCH_DOCUMENT_ID.getTypeID()
939 +
" LEFT JOIN blackboard_attributes as account_type ON blackboard_artifacts.artifact_id = account_type.artifact_id "
940 +
" AND account_type.attribute_type_id = " + BlackboardAttribute.ATTRIBUTE_TYPE.TSK_ACCOUNT_TYPE.getTypeID()
941 +
" AND account_type.value_text = '" + Account.Type.CREDIT_CARD.getTypeName() +
"'"
942 +
" WHERE blackboard_artifacts.artifact_type_id = " + BlackboardArtifact.Type.TSK_ACCOUNT.getTypeID()
945 +
" GROUP BY blackboard_artifacts.obj_id, solr_document_id "
946 +
" ORDER BY hits DESC ";
947 try (SleuthkitCase.CaseDbQuery results = skCase.executeQuery(query);
948 ResultSet resultSet = results.getResultSet();) {
949 while (resultSet.next()) {
951 resultSet.getLong(
"obj_id"),
952 resultSet.getString(
"solr_document_id"),
953 unGroupConcat(resultSet.getString(
"artifact_IDs"), Long::valueOf),
954 resultSet.getLong(
"hits"),
955 new HashSet<>(unGroupConcat(resultSet.getString(
"review_status_ids"), reviewStatusID -> BlackboardArtifact.ReviewStatus.withID(Integer.valueOf(reviewStatusID))))));
957 }
catch (TskCoreException | SQLException ex) {
958 LOGGER.log(Level.SEVERE,
"Error querying for files with ccn hits.", ex);
968 List<Object> lookupContents =
new ArrayList<>();
970 lookupContents.add(skCase.getBlackboardArtifact(artId));
972 AbstractFile abstractFileById = skCase.getAbstractFileById(key.
getObjID());
973 lookupContents.add(abstractFileById);
974 return new Node[]{
new FileWithCCNNode(key, abstractFileById, lookupContents.toArray())};
975 }
catch (TskCoreException ex) {
976 LOGGER.log(Level.SEVERE,
"Error getting content for file with ccn hits.", ex);
995 this.setIconBaseWithExtension(
"org/sleuthkit/autopsy/images/file-icon.png");
996 reviewStatusBus.register(
this);
1000 "# {0} - number of children",
1001 "Accounts.ByFileNode.displayName=By File ({0})"})
1004 =
"SELECT count(*) FROM ( SELECT count(*) AS documents "
1005 +
" FROM blackboard_artifacts "
1006 +
" LEFT JOIN blackboard_attributes as solr_attribute ON blackboard_artifacts.artifact_id = solr_attribute.artifact_id "
1007 +
" AND solr_attribute.attribute_type_id = " + BlackboardAttribute.ATTRIBUTE_TYPE.TSK_KEYWORD_SEARCH_DOCUMENT_ID.getTypeID()
1008 +
" LEFT JOIN blackboard_attributes as account_type ON blackboard_artifacts.artifact_id = account_type.artifact_id "
1009 +
" AND account_type.attribute_type_id = " + BlackboardAttribute.ATTRIBUTE_TYPE.TSK_ACCOUNT_TYPE.getTypeID()
1010 +
" AND account_type.value_text = '" + Account.Type.CREDIT_CARD.getTypeName() +
"'"
1011 +
" WHERE blackboard_artifacts.artifact_type_id = " + BlackboardArtifact.Type.TSK_ACCOUNT.getTypeID()
1014 +
" GROUP BY blackboard_artifacts.obj_id, solr_attribute.value_text ) AS foo";
1015 try (SleuthkitCase.CaseDbQuery results = skCase.executeQuery(query);
1016 ResultSet resultSet = results.getResultSet();) {
1017 while (resultSet.next()) {
1018 if (skCase.getDatabaseType().equals(DbType.POSTGRESQL)) {
1019 setDisplayName(Bundle.Accounts_ByFileNode_displayName(resultSet.getLong(
"count")));
1021 setDisplayName(Bundle.Accounts_ByFileNode_displayName(resultSet.getLong(
"count(*)")));
1024 }
catch (TskCoreException | SQLException ex) {
1025 LOGGER.log(Level.SEVERE,
"Error querying for files with ccn hits.", ex);
1037 return visitor.
visit(
this);
1042 return getClass().getName();
1047 updateDisplayName();
1052 updateDisplayName();
1058 private final PropertyChangeListener pcl =
new PropertyChangeListener() {
1060 public void propertyChange(PropertyChangeEvent evt) {
1061 String eventType = evt.getPropertyName();
1078 if (null != eventData
1080 reviewStatusBus.post(eventData);
1101 && (evt.getNewValue() == null)) {
1109 private final PropertyChangeListener weakPcl = WeakListeners.propertyChange(pcl, null);
1142 RangeMap<Integer, BinResult> binRanges = TreeRangeMap.create();
1145 =
"SELECT SUBSTR(blackboard_attributes.value_text,1,8) AS BIN, "
1146 +
" COUNT(blackboard_artifacts.artifact_id) AS count "
1147 +
" FROM blackboard_artifacts "
1148 +
" JOIN blackboard_attributes ON blackboard_artifacts.artifact_id = blackboard_attributes.artifact_id"
1149 +
" WHERE blackboard_artifacts.artifact_type_id = " + BlackboardArtifact.Type.TSK_ACCOUNT.getTypeID()
1150 +
" AND blackboard_attributes.attribute_type_id = " + BlackboardAttribute.ATTRIBUTE_TYPE.TSK_CARD_NUMBER.getTypeID()
1155 try (SleuthkitCase.CaseDbQuery results = skCase.executeQuery(query);
1156 ResultSet resultSet = results.getResultSet();) {
1158 while (resultSet.next()) {
1159 final Integer bin = Integer.valueOf(resultSet.getString(
"BIN"));
1160 long count = resultSet.getLong(
"count");
1163 BinResult previousResult = binRanges.get(bin);
1165 if (previousResult != null) {
1166 binRanges.remove(Range.closed(previousResult.getBINStart(), previousResult.getBINEnd()));
1167 count += previousResult.getCount();
1170 if (binRange == null) {
1171 binRanges.put(Range.closed(bin, bin),
new BinResult(count, bin, bin));
1176 binRanges.asMapOfRanges().values().forEach(list::add);
1177 }
catch (TskCoreException | SQLException ex) {
1178 LOGGER.log(Level.SEVERE,
"Error querying for BINs.", ex);
1186 return new Node[]{
new BINNode(key)};
1199 @NbBundle.Messages(
"Accounts.ByBINNode.name=By BIN")
1201 super(Children.create(
new BINFactory(),
true), Lookups.singleton(Bundle.Accounts_ByBINNode_name()));
1202 setName(Bundle.Accounts_ByBINNode_name());
1203 updateDisplayName();
1204 this.setIconBaseWithExtension(
"org/sleuthkit/autopsy/images/bank.png");
1205 reviewStatusBus.register(
this);
1208 @NbBundle.Messages({
1209 "# {0} - number of children",
1210 "Accounts.ByBINNode.displayName=By BIN ({0})"})
1213 =
"SELECT count(distinct SUBSTR(blackboard_attributes.value_text,1,8)) AS BINs "
1214 +
" FROM blackboard_artifacts "
1215 +
" JOIN blackboard_attributes ON blackboard_artifacts.artifact_id = blackboard_attributes.artifact_id"
1216 +
" WHERE blackboard_artifacts.artifact_type_id = " + BlackboardArtifact.Type.TSK_ACCOUNT.getTypeID()
1217 +
" AND blackboard_attributes.attribute_type_id = " + BlackboardAttribute.ATTRIBUTE_TYPE.TSK_CARD_NUMBER.getTypeID()
1220 try (SleuthkitCase.CaseDbQuery results = skCase.executeQuery(query);
1221 ResultSet resultSet = results.getResultSet();) {
1222 while (resultSet.next()) {
1223 setDisplayName(Bundle.Accounts_ByBINNode_displayName(resultSet.getLong(
"BINs")));
1225 }
catch (TskCoreException | SQLException ex) {
1226 LOGGER.log(Level.SEVERE,
"Error querying for BINs.", ex);
1237 return visitor.
visit(
this);
1242 return getClass().getName();
1247 updateDisplayName();
1252 updateDisplayName();
1266 hash = 79 * hash + (int) (this.objID ^ (this.objID >>> 32));
1267 hash = 79 * hash + Objects.hashCode(this.keywordSearchDocID);
1268 hash = 79 * hash + Objects.hashCode(this.artifactIDs);
1269 hash = 79 * hash + (int) (this.hits ^ (this.hits >>> 32));
1270 hash = 79 * hash + Objects.hashCode(this.statuses);
1282 if (getClass() != obj.getClass()) {
1286 if (this.objID != other.
objID) {
1289 if (this.hits != other.
hits) {
1295 if (!Objects.equals(
this.artifactIDs, other.
artifactIDs)) {
1298 if (!Objects.equals(
this.statuses, other.
statuses)) {
1308 private final Set<BlackboardArtifact.ReviewStatus>
statuses;
1310 private FileWithCCN(
long objID, String solrDocID, List<Long> artifactIDs,
long hits, Set<BlackboardArtifact.ReviewStatus> statuses) {
1312 this.keywordSearchDocID = solrDocID;
1313 this.artifactIDs = artifactIDs;
1315 this.statuses = statuses;
1334 return keywordSearchDocID;
1343 return Collections.unmodifiableList(artifactIDs);
1361 return Collections.unmodifiableSet(statuses);
1381 static <X> List<X> unGroupConcat(String groupConcat, Function<String, X> mapper) {
1382 return StringUtils.isBlank(groupConcat) ? Collections.emptyList()
1383 : Stream.of(groupConcat.split(
","))
1385 .collect(Collectors.toList());
1405 @NbBundle.Messages({
1406 "# {0} - raw file name",
1407 "# {1} - solr chunk id",
1408 "Accounts.FileWithCCNNode.unallocatedSpaceFile.displayName={0}_chunk_{1}"})
1410 super(Children.LEAF, Lookups.fixed(lookupContents));
1414 : Bundle.Accounts_FileWithCCNNode_unallocatedSpaceFile_displayName(content.getName(), StringUtils.substringAfter(key.
getkeywordSearchDocID(),
"_"));
1415 setName(fileName + key.
getObjID());
1416 setDisplayName(fileName);
1426 return visitor.
visit(
this);
1431 return getClass().getName();
1435 @NbBundle.Messages({
1436 "Accounts.FileWithCCNNode.nameProperty.displayName=File",
1437 "Accounts.FileWithCCNNode.accountsProperty.displayName=Accounts",
1438 "Accounts.FileWithCCNNode.statusProperty.displayName=Status",
1439 "Accounts.FileWithCCNNode.noDescription=no description"})
1441 Sheet sheet = super.createSheet();
1442 Sheet.Set propSet = sheet.get(Sheet.PROPERTIES);
1443 if (propSet == null) {
1444 propSet = Sheet.createPropertiesSet();
1448 propSet.put(
new NodeProperty<>(Bundle.Accounts_FileWithCCNNode_nameProperty_displayName(),
1449 Bundle.Accounts_FileWithCCNNode_nameProperty_displayName(),
1450 Bundle.Accounts_FileWithCCNNode_noDescription(),
1452 propSet.put(
new NodeProperty<>(Bundle.Accounts_FileWithCCNNode_accountsProperty_displayName(),
1453 Bundle.Accounts_FileWithCCNNode_accountsProperty_displayName(),
1454 Bundle.Accounts_FileWithCCNNode_noDescription(),
1456 propSet.put(
new NodeProperty<>(Bundle.Accounts_FileWithCCNNode_statusProperty_displayName(),
1457 Bundle.Accounts_FileWithCCNNode_statusProperty_displayName(),
1458 Bundle.Accounts_FileWithCCNNode_noDescription(),
1460 .map(BlackboardArtifact.ReviewStatus::getDisplayName)
1461 .collect(Collectors.joining(
", "))));
1468 Action[] actions = super.getActions(context);
1469 ArrayList<Action> arrayList =
new ArrayList<>();
1470 arrayList.addAll(Arrays.asList(actions));
1473 }
catch (TskCoreException ex) {
1474 LOGGER.log(Level.SEVERE,
"Error gettung content by id", ex);
1477 arrayList.add(approveActionInstance);
1478 arrayList.add(rejectActionInstance);
1480 return arrayList.toArray(
new Action[arrayList.size()]);
1508 =
"SELECT blackboard_artifacts.artifact_obj_id "
1509 +
" FROM blackboard_artifacts "
1510 +
" JOIN blackboard_attributes ON blackboard_artifacts.artifact_id = blackboard_attributes.artifact_id "
1511 +
" WHERE blackboard_artifacts.artifact_type_id = " + BlackboardArtifact.Type.TSK_ACCOUNT.getTypeID()
1512 +
" AND blackboard_attributes.attribute_type_id = " + BlackboardAttribute.ATTRIBUTE_TYPE.TSK_CARD_NUMBER.getTypeID()
1513 +
" AND blackboard_attributes.value_text >= '" + bin.getBINStart() +
"' AND blackboard_attributes.value_text < '" + (bin.getBINEnd() + 1) +
"'"
1516 +
" ORDER BY blackboard_attributes.value_text";
1517 try (SleuthkitCase.CaseDbQuery results = skCase.executeQuery(query);
1518 ResultSet rs = results.getResultSet();) {
1520 list.add(skCase.getBlackboard().getDataArtifactById(rs.getLong(
"artifact_obj_id")));
1522 }
catch (TskCoreException | SQLException ex) {
1523 LOGGER.log(Level.SEVERE,
"Error querying for account artifacts.", ex);
1536 if (bin.getBINStart() == bin.getBINEnd()) {
1537 return Integer.toString(bin.getBINStart());
1539 return bin.getBINStart() +
"-" + StringUtils.difference(bin.getBINStart() +
"", bin.getBINEnd() +
"");
1554 updateDisplayName();
1555 this.setIconBaseWithExtension(
"org/sleuthkit/autopsy/images/bank.png");
1556 reviewStatusBus.register(
this);
1561 updateDisplayName();
1567 updateDisplayName();
1572 =
"SELECT count(blackboard_artifacts.artifact_id ) AS count"
1573 +
" FROM blackboard_artifacts "
1574 +
" JOIN blackboard_attributes ON blackboard_artifacts.artifact_id = blackboard_attributes.artifact_id "
1575 +
" WHERE blackboard_artifacts.artifact_type_id = " + BlackboardArtifact.Type.TSK_ACCOUNT.getTypeID()
1576 +
" AND blackboard_attributes.attribute_type_id = " + BlackboardAttribute.ATTRIBUTE_TYPE.TSK_CARD_NUMBER.getTypeID()
1577 +
" AND blackboard_attributes.value_text >= '" + bin.getBINStart() +
"' AND blackboard_attributes.value_text < '" + (bin.getBINEnd() + 1) +
"'"
1580 try (SleuthkitCase.CaseDbQuery results = skCase.executeQuery(query);
1581 ResultSet resultSet = results.getResultSet();) {
1582 while (resultSet.next()) {
1583 setDisplayName(
getBinRangeString(bin) +
" (" + resultSet.getLong(
"count") +
")");
1585 }
catch (TskCoreException | SQLException ex) {
1586 LOGGER.log(Level.SEVERE,
"Error querying for account artifacts.", ex);
1599 return visitor.
visit(
this);
1604 return getClass().getName();
1608 Sheet.Set sheetSet = sheet.get(Sheet.PROPERTIES);
1609 if (sheetSet == null) {
1610 sheetSet = Sheet.createPropertiesSet();
1611 sheet.put(sheetSet);
1617 @NbBundle.Messages({
1618 "Accounts.BINNode.binProperty.displayName=Bank Identifier Number",
1619 "Accounts.BINNode.accountsProperty.displayName=Accounts",
1620 "Accounts.BINNode.cardTypeProperty.displayName=Payment Card Type",
1621 "Accounts.BINNode.schemeProperty.displayName=Credit Card Scheme",
1622 "Accounts.BINNode.brandProperty.displayName=Brand",
1623 "Accounts.BINNode.bankProperty.displayName=Bank",
1624 "Accounts.BINNode.bankCityProperty.displayName=Bank City",
1625 "Accounts.BINNode.bankCountryProperty.displayName=Bank Country",
1626 "Accounts.BINNode.bankPhoneProperty.displayName=Bank Phone #",
1627 "Accounts.BINNode.bankURLProperty.displayName=Bank URL",
1628 "Accounts.BINNode.noDescription=no description"})
1630 Sheet sheet = super.createSheet();
1631 Sheet.Set properties = getPropertySet(sheet);
1633 properties.put(
new NodeProperty<>(Bundle.Accounts_BINNode_binProperty_displayName(),
1634 Bundle.Accounts_BINNode_binProperty_displayName(),
1635 Bundle.Accounts_BINNode_noDescription(),
1637 properties.put(
new NodeProperty<>(Bundle.Accounts_BINNode_accountsProperty_displayName(),
1638 Bundle.Accounts_BINNode_accountsProperty_displayName(), Bundle.Accounts_BINNode_noDescription(),
1642 if (bin.hasDetails()) {
1643 bin.
getCardType().ifPresent(cardType -> properties.put(
new NodeProperty<>(Bundle.Accounts_BINNode_cardTypeProperty_displayName(),
1644 Bundle.Accounts_BINNode_cardTypeProperty_displayName(), Bundle.Accounts_BINNode_noDescription(),
1646 bin.
getScheme().ifPresent(scheme -> properties.put(
new NodeProperty<>(Bundle.Accounts_BINNode_schemeProperty_displayName(),
1647 Bundle.Accounts_BINNode_schemeProperty_displayName(), Bundle.Accounts_BINNode_noDescription(),
1649 bin.
getBrand().ifPresent(brand -> properties.put(
new NodeProperty<>(Bundle.Accounts_BINNode_brandProperty_displayName(),
1650 Bundle.Accounts_BINNode_brandProperty_displayName(), Bundle.Accounts_BINNode_noDescription(),
1652 bin.
getBankName().ifPresent(bankName -> properties.put(
new NodeProperty<>(Bundle.Accounts_BINNode_bankProperty_displayName(),
1653 Bundle.Accounts_BINNode_bankProperty_displayName(), Bundle.Accounts_BINNode_noDescription(),
1655 bin.
getBankCity().ifPresent(bankCity -> properties.put(
new NodeProperty<>(Bundle.Accounts_BINNode_bankCityProperty_displayName(),
1656 Bundle.Accounts_BINNode_bankCityProperty_displayName(), Bundle.Accounts_BINNode_noDescription(),
1658 bin.
getCountry().ifPresent(country -> properties.put(
new NodeProperty<>(Bundle.Accounts_BINNode_bankCountryProperty_displayName(),
1659 Bundle.Accounts_BINNode_bankCountryProperty_displayName(), Bundle.Accounts_BINNode_noDescription(),
1662 Bundle.Accounts_BINNode_bankPhoneProperty_displayName(), Bundle.Accounts_BINNode_noDescription(),
1664 bin.
getBankURL().ifPresent(url -> properties.put(
new NodeProperty<>(Bundle.Accounts_BINNode_bankURLProperty_displayName(),
1665 Bundle.Accounts_BINNode_bankURLProperty_displayName(), Bundle.Accounts_BINNode_noDescription(),
1672 this.setSheet(createSheet());
1687 hash = 97 * hash + this.binEnd;
1688 hash = 97 * hash + this.binStart;
1700 if (getClass() != obj.getClass()) {
1704 if (this.binEnd != other.
binEnd) {
1707 if (this.binStart != other.
binStart) {
1724 this.binRange = binRange;
1725 binStart = binRange.getBINstart();
1726 binEnd = binRange.getBINend();
1731 this.binRange = null;
1748 boolean hasDetails() {
1749 return binRange != null;
1803 super(artifact,
"org/sleuthkit/autopsy/images/credit-card.png");
1804 this.artifact = artifact;
1805 setName(Long.toString(
this.artifact.getArtifactID()));
1807 reviewStatusBus.register(
this);
1812 List<Action> actionsList =
new ArrayList<>();
1813 actionsList.addAll(Arrays.asList(super.getActions(context)));
1815 actionsList.add(approveActionInstance);
1816 actionsList.add(rejectActionInstance);
1818 return actionsList.toArray(
new Action[actionsList.size()]);
1823 Sheet sheet = super.createSheet();
1824 Sheet.Set properties = sheet.get(Sheet.PROPERTIES);
1825 if (properties == null) {
1826 properties = Sheet.createPropertiesSet();
1827 sheet.put(properties);
1829 properties.put(
new NodeProperty<>(Bundle.Accounts_FileWithCCNNode_statusProperty_displayName(),
1830 Bundle.Accounts_FileWithCCNNode_statusProperty_displayName(),
1831 Bundle.Accounts_FileWithCCNNode_noDescription(),
1832 artifact.getReviewStatus().getDisplayName()));
1841 event.artifacts.stream().filter((art) -> (art.getArtifactID() == this.artifact.getArtifactID())).map((_item) -> {
1843 }).forEachOrdered((_item) -> {
1849 this.setSheet(createSheet());
1857 @NbBundle.Messages(
"ToggleShowRejected.name=Show Rejected Results")
1859 super(Bundle.ToggleShowRejected_name());
1885 this.newStatus = newStatus;
1896 List<String[]> selectedPaths = Utilities.actionsGlobalContext().lookupAll(Node.class).stream()
1898 String[] createPath;
1904 if (newStatus == BlackboardArtifact.ReviewStatus.REJECTED && showRejected ==
false) {
1905 List<Node> siblings = Arrays.asList(node.getParentNode().getChildren().getNodes());
1906 if (siblings.size() > 1) {
1907 int indexOf = siblings.indexOf(node);
1909 Node sibling = indexOf > 0
1910 ? siblings.get(indexOf - 1)
1911 : siblings.get(Integer.max(indexOf + 1, siblings.size() - 1));
1912 createPath = NodeOp.createPath(sibling, null);
1922 createPath = NodeOp.createPath(node, null);
1925 return Arrays.copyOfRange(createPath, 1, createPath.length);
1927 .filter(Objects::nonNull)
1928 .collect(Collectors.toList());
1931 final Collection<? extends BlackboardArtifact> artifacts = Utilities.actionsGlobalContext().lookupAll(BlackboardArtifact.class);
1932 artifacts.forEach(artifact -> {
1934 artifact.setReviewStatus(newStatus);
1935 }
catch (TskCoreException ex) {
1936 LOGGER.log(Level.SEVERE,
"Error changing artifact review status.", ex);
1940 reviewStatusBus.post(
new ReviewStatusChangeEvent(artifacts, newStatus));
1942 final DataResultTopComponent directoryListing = DirectoryTreeTopComponent.findInstance().getDirectoryListing();
1943 final Node rootNode = directoryListing.getRootNode();
1946 List<Node> toArray =
new ArrayList<>();
1947 selectedPaths.forEach(path -> {
1949 toArray.add(NodeOp.findPath(rootNode, path));
1950 }
catch (NodeNotFoundException ex) {
1955 directoryListing.setSelectedNodes(toArray.toArray(
new Node[toArray.size()]));
1961 @NbBundle.Messages({
"ApproveAccountsAction.name=Approve Accounts"})
1963 super(Bundle.ApproveAccountsAction_name(), BlackboardArtifact.ReviewStatus.APPROVED);
1969 @NbBundle.Messages({
"RejectAccountsAction.name=Reject Accounts"})
1971 super(Bundle.RejectAccountsAction_name(), BlackboardArtifact.ReviewStatus.REJECTED);
1977 Collection<? extends BlackboardArtifact> artifacts;
1978 BlackboardArtifact.ReviewStatus newReviewStatus;
1980 ReviewStatusChangeEvent(Collection<? extends BlackboardArtifact> artifacts, BlackboardArtifact.ReviewStatus newReviewStatus) {
1981 this.artifacts = artifacts;
1982 this.newReviewStatus = newReviewStatus;
1993 if (type.equals(Account.Type.CREDIT_CARD)) {
1994 return ICON_BASE_PATH +
"credit-card.png";
1995 }
else if (type.equals(Account.Type.DEVICE)) {
1996 return ICON_BASE_PATH +
"image.png";
1997 }
else if (type.equals(Account.Type.EMAIL)) {
1998 return ICON_BASE_PATH +
"email.png";
1999 }
else if (type.equals(Account.Type.FACEBOOK)) {
2000 return ICON_BASE_PATH +
"facebook.png";
2001 }
else if (type.equals(Account.Type.INSTAGRAM)) {
2002 return ICON_BASE_PATH +
"instagram.png";
2003 }
else if (type.equals(Account.Type.MESSAGING_APP)) {
2004 return ICON_BASE_PATH +
"messaging.png";
2005 }
else if (type.equals(Account.Type.PHONE)) {
2006 return ICON_BASE_PATH +
"phone.png";
2007 }
else if (type.equals(Account.Type.TWITTER)) {
2008 return ICON_BASE_PATH +
"twitter.png";
2009 }
else if (type.equals(Account.Type.WEBSITE)) {
2010 return ICON_BASE_PATH +
"web-file.png";
2011 }
else if (type.equals(Account.Type.WHATSAPP)) {
2012 return ICON_BASE_PATH +
"WhatsApp.png";
2015 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)
FileWithCCN(long objID, String solrDocID, List< Long > artifactIDs, long hits, Set< BlackboardArtifact.ReviewStatus > statuses)
void actionPerformed(ActionEvent e)
boolean createKeys(List< BinResult > list)
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)