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_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(rs.getLong(
"artifact_id"));
1522 }
catch (TskCoreException | SQLException ex) {
1523 LOGGER.log(Level.SEVERE,
"Error querying for account artifacts.", ex);
1531 if (skCase == null) {
1536 DataArtifact art = skCase.getBlackboard().getDataArtifactById(artifactID);
1538 }
catch (TskCoreException ex) {
1539 LOGGER.log(Level.SEVERE,
"Error creating BlackboardArtifactNode for artifact with ID " + artifactID, ex);
1546 if (bin.getBINStart() == bin.getBINEnd()) {
1547 return Integer.toString(bin.getBINStart());
1549 return bin.getBINStart() +
"-" + StringUtils.difference(bin.getBINStart() +
"", bin.getBINEnd() +
"");
1564 updateDisplayName();
1565 this.setIconBaseWithExtension(
"org/sleuthkit/autopsy/images/bank.png");
1566 reviewStatusBus.register(
this);
1571 updateDisplayName();
1577 updateDisplayName();
1582 =
"SELECT count(blackboard_artifacts.artifact_id ) AS count"
1583 +
" FROM blackboard_artifacts "
1584 +
" JOIN blackboard_attributes ON blackboard_artifacts.artifact_id = blackboard_attributes.artifact_id "
1585 +
" WHERE blackboard_artifacts.artifact_type_id = " + BlackboardArtifact.Type.TSK_ACCOUNT.getTypeID()
1586 +
" AND blackboard_attributes.attribute_type_id = " + BlackboardAttribute.ATTRIBUTE_TYPE.TSK_CARD_NUMBER.getTypeID()
1587 +
" AND blackboard_attributes.value_text >= '" + bin.getBINStart() +
"' AND blackboard_attributes.value_text < '" + (bin.getBINEnd() + 1) +
"'"
1590 try (SleuthkitCase.CaseDbQuery results = skCase.executeQuery(query);
1591 ResultSet resultSet = results.getResultSet();) {
1592 while (resultSet.next()) {
1593 setDisplayName(
getBinRangeString(bin) +
" (" + resultSet.getLong(
"count") +
")");
1595 }
catch (TskCoreException | SQLException ex) {
1596 LOGGER.log(Level.SEVERE,
"Error querying for account artifacts.", ex);
1609 return visitor.
visit(
this);
1614 return getClass().getName();
1618 Sheet.Set sheetSet = sheet.get(Sheet.PROPERTIES);
1619 if (sheetSet == null) {
1620 sheetSet = Sheet.createPropertiesSet();
1621 sheet.put(sheetSet);
1627 @NbBundle.Messages({
1628 "Accounts.BINNode.binProperty.displayName=Bank Identifier Number",
1629 "Accounts.BINNode.accountsProperty.displayName=Accounts",
1630 "Accounts.BINNode.cardTypeProperty.displayName=Payment Card Type",
1631 "Accounts.BINNode.schemeProperty.displayName=Credit Card Scheme",
1632 "Accounts.BINNode.brandProperty.displayName=Brand",
1633 "Accounts.BINNode.bankProperty.displayName=Bank",
1634 "Accounts.BINNode.bankCityProperty.displayName=Bank City",
1635 "Accounts.BINNode.bankCountryProperty.displayName=Bank Country",
1636 "Accounts.BINNode.bankPhoneProperty.displayName=Bank Phone #",
1637 "Accounts.BINNode.bankURLProperty.displayName=Bank URL",
1638 "Accounts.BINNode.noDescription=no description"})
1640 Sheet sheet = super.createSheet();
1641 Sheet.Set properties = getPropertySet(sheet);
1643 properties.put(
new NodeProperty<>(Bundle.Accounts_BINNode_binProperty_displayName(),
1644 Bundle.Accounts_BINNode_binProperty_displayName(),
1645 Bundle.Accounts_BINNode_noDescription(),
1647 properties.put(
new NodeProperty<>(Bundle.Accounts_BINNode_accountsProperty_displayName(),
1648 Bundle.Accounts_BINNode_accountsProperty_displayName(), Bundle.Accounts_BINNode_noDescription(),
1652 if (bin.hasDetails()) {
1653 bin.
getCardType().ifPresent(cardType -> properties.put(
new NodeProperty<>(Bundle.Accounts_BINNode_cardTypeProperty_displayName(),
1654 Bundle.Accounts_BINNode_cardTypeProperty_displayName(), Bundle.Accounts_BINNode_noDescription(),
1656 bin.
getScheme().ifPresent(scheme -> properties.put(
new NodeProperty<>(Bundle.Accounts_BINNode_schemeProperty_displayName(),
1657 Bundle.Accounts_BINNode_schemeProperty_displayName(), Bundle.Accounts_BINNode_noDescription(),
1659 bin.
getBrand().ifPresent(brand -> properties.put(
new NodeProperty<>(Bundle.Accounts_BINNode_brandProperty_displayName(),
1660 Bundle.Accounts_BINNode_brandProperty_displayName(), Bundle.Accounts_BINNode_noDescription(),
1662 bin.
getBankName().ifPresent(bankName -> properties.put(
new NodeProperty<>(Bundle.Accounts_BINNode_bankProperty_displayName(),
1663 Bundle.Accounts_BINNode_bankProperty_displayName(), Bundle.Accounts_BINNode_noDescription(),
1665 bin.
getBankCity().ifPresent(bankCity -> properties.put(
new NodeProperty<>(Bundle.Accounts_BINNode_bankCityProperty_displayName(),
1666 Bundle.Accounts_BINNode_bankCityProperty_displayName(), Bundle.Accounts_BINNode_noDescription(),
1668 bin.
getCountry().ifPresent(country -> properties.put(
new NodeProperty<>(Bundle.Accounts_BINNode_bankCountryProperty_displayName(),
1669 Bundle.Accounts_BINNode_bankCountryProperty_displayName(), Bundle.Accounts_BINNode_noDescription(),
1672 Bundle.Accounts_BINNode_bankPhoneProperty_displayName(), Bundle.Accounts_BINNode_noDescription(),
1674 bin.
getBankURL().ifPresent(url -> properties.put(
new NodeProperty<>(Bundle.Accounts_BINNode_bankURLProperty_displayName(),
1675 Bundle.Accounts_BINNode_bankURLProperty_displayName(), Bundle.Accounts_BINNode_noDescription(),
1682 this.setSheet(createSheet());
1697 hash = 97 * hash + this.binEnd;
1698 hash = 97 * hash + this.binStart;
1710 if (getClass() != obj.getClass()) {
1714 if (this.binEnd != other.
binEnd) {
1717 if (this.binStart != other.
binStart) {
1734 this.binRange = binRange;
1735 binStart = binRange.getBINstart();
1736 binEnd = binRange.getBINend();
1741 this.binRange = null;
1758 boolean hasDetails() {
1759 return binRange != null;
1813 super(artifact,
"org/sleuthkit/autopsy/images/credit-card.png");
1814 this.artifact = artifact;
1815 setName(Long.toString(
this.artifact.getArtifactID()));
1817 reviewStatusBus.register(
this);
1822 List<Action> actionsList =
new ArrayList<>();
1823 actionsList.addAll(Arrays.asList(super.getActions(context)));
1825 actionsList.add(approveActionInstance);
1826 actionsList.add(rejectActionInstance);
1828 return actionsList.toArray(
new Action[actionsList.size()]);
1833 Sheet sheet = super.createSheet();
1834 Sheet.Set properties = sheet.get(Sheet.PROPERTIES);
1835 if (properties == null) {
1836 properties = Sheet.createPropertiesSet();
1837 sheet.put(properties);
1839 properties.put(
new NodeProperty<>(Bundle.Accounts_FileWithCCNNode_statusProperty_displayName(),
1840 Bundle.Accounts_FileWithCCNNode_statusProperty_displayName(),
1841 Bundle.Accounts_FileWithCCNNode_noDescription(),
1842 artifact.getReviewStatus().getDisplayName()));
1851 event.artifacts.stream().filter((art) -> (art.getArtifactID() == this.artifact.getArtifactID())).map((_item) -> {
1853 }).forEachOrdered((_item) -> {
1859 this.setSheet(createSheet());
1867 @NbBundle.Messages(
"ToggleShowRejected.name=Show Rejected Results")
1869 super(Bundle.ToggleShowRejected_name());
1895 this.newStatus = newStatus;
1906 List<String[]> selectedPaths = Utilities.actionsGlobalContext().lookupAll(Node.class).stream()
1908 String[] createPath;
1914 if (newStatus == BlackboardArtifact.ReviewStatus.REJECTED && showRejected ==
false) {
1915 List<Node> siblings = Arrays.asList(node.getParentNode().getChildren().getNodes());
1916 if (siblings.size() > 1) {
1917 int indexOf = siblings.indexOf(node);
1919 Node sibling = indexOf > 0
1920 ? siblings.get(indexOf - 1)
1921 : siblings.get(Integer.max(indexOf + 1, siblings.size() - 1));
1922 createPath = NodeOp.createPath(sibling, null);
1932 createPath = NodeOp.createPath(node, null);
1935 return Arrays.copyOfRange(createPath, 1, createPath.length);
1937 .filter(Objects::nonNull)
1938 .collect(Collectors.toList());
1941 final Collection<? extends BlackboardArtifact> artifacts = Utilities.actionsGlobalContext().lookupAll(BlackboardArtifact.class);
1942 artifacts.forEach(artifact -> {
1944 artifact.setReviewStatus(newStatus);
1945 }
catch (TskCoreException ex) {
1946 LOGGER.log(Level.SEVERE,
"Error changing artifact review status.", ex);
1950 reviewStatusBus.post(
new ReviewStatusChangeEvent(artifacts, newStatus));
1952 final DataResultTopComponent directoryListing = DirectoryTreeTopComponent.findInstance().getDirectoryListing();
1953 final Node rootNode = directoryListing.getRootNode();
1956 List<Node> toArray =
new ArrayList<>();
1957 selectedPaths.forEach(path -> {
1959 toArray.add(NodeOp.findPath(rootNode, path));
1960 }
catch (NodeNotFoundException ex) {
1965 directoryListing.setSelectedNodes(toArray.toArray(
new Node[toArray.size()]));
1971 @NbBundle.Messages({
"ApproveAccountsAction.name=Approve Accounts"})
1973 super(Bundle.ApproveAccountsAction_name(), BlackboardArtifact.ReviewStatus.APPROVED);
1979 @NbBundle.Messages({
"RejectAccountsAction.name=Reject Accounts"})
1981 super(Bundle.RejectAccountsAction_name(), BlackboardArtifact.ReviewStatus.REJECTED);
1987 Collection<? extends BlackboardArtifact> artifacts;
1988 BlackboardArtifact.ReviewStatus newReviewStatus;
1990 ReviewStatusChangeEvent(Collection<? extends BlackboardArtifact> artifacts, BlackboardArtifact.ReviewStatus newReviewStatus) {
1991 this.artifacts = artifacts;
1992 this.newReviewStatus = newReviewStatus;
2003 if (type.equals(Account.Type.CREDIT_CARD)) {
2004 return ICON_BASE_PATH +
"credit-card.png";
2005 }
else if (type.equals(Account.Type.DEVICE)) {
2006 return ICON_BASE_PATH +
"image.png";
2007 }
else if (type.equals(Account.Type.EMAIL)) {
2008 return ICON_BASE_PATH +
"email.png";
2009 }
else if (type.equals(Account.Type.FACEBOOK)) {
2010 return ICON_BASE_PATH +
"facebook.png";
2011 }
else if (type.equals(Account.Type.INSTAGRAM)) {
2012 return ICON_BASE_PATH +
"instagram.png";
2013 }
else if (type.equals(Account.Type.MESSAGING_APP)) {
2014 return ICON_BASE_PATH +
"messaging.png";
2015 }
else if (type.equals(Account.Type.PHONE)) {
2016 return ICON_BASE_PATH +
"phone.png";
2017 }
else if (type.equals(Account.Type.TWITTER)) {
2018 return ICON_BASE_PATH +
"twitter.png";
2019 }
else if (type.equals(Account.Type.WEBSITE)) {
2020 return ICON_BASE_PATH +
"web-file.png";
2021 }
else if (type.equals(Account.Type.WHATSAPP)) {
2022 return ICON_BASE_PATH +
"WhatsApp.png";
2025 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()
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)
Node[] createNodesForKey(Long artifactID)
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()
boolean createKeys(List< Long > list)
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)