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.HashSet;
37 import java.util.List;
38 import java.util.Objects;
39 import java.util.Optional;
41 import java.util.function.Function;
42 import java.util.logging.Level;
43 import java.util.stream.Collectors;
44 import java.util.stream.Stream;
45 import javax.annotation.Nonnull;
46 import javax.annotation.concurrent.Immutable;
47 import javax.swing.AbstractAction;
48 import javax.swing.Action;
49 import org.apache.commons.lang3.StringUtils;
50 import org.openide.nodes.ChildFactory;
51 import org.openide.nodes.Children;
52 import org.openide.nodes.Node;
53 import org.openide.nodes.NodeNotFoundException;
54 import org.openide.nodes.NodeOp;
55 import org.openide.nodes.Sheet;
56 import org.openide.util.NbBundle;
57 import org.openide.util.Utilities;
58 import org.openide.util.lookup.Lookups;
77 import org.
sleuthkit.datamodel.BlackboardArtifact.ARTIFACT_TYPE;
91 private static final String
ICON_BASE_PATH =
"/org/sleuthkit/autopsy/images/";
95 @NbBundle.Messages(
"AccountsRootNode.name=Accounts")
96 final public static String
NAME = Bundle.AccountsRootNode_name();
126 public Accounts(SleuthkitCase skCase,
long objId) {
128 this.filteringDSObjId = objId;
136 return visitor.
visit(
this);
147 return showRejected ?
" " :
" AND blackboard_artifacts.review_status_id != " + BlackboardArtifact.ReviewStatus.REJECTED.getID() +
" ";
157 if (filteringDSObjId > 0) {
158 return " AND blackboard_artifacts.data_source_obj_id = " + filteringDSObjId +
" ";
197 abstract protected boolean createKeys(List<X> list);
212 super.removeNotify();
227 @NbBundle.Messages({
"Accounts.RootNode.displayName=Accounts"})
233 setDisplayName(Bundle.Accounts_RootNode_displayName());
234 this.setIconBaseWithExtension(
"org/sleuthkit/autopsy/images/accounts.png");
244 return visitor.
visit(
this);
249 return getClass().getName();
262 private final PropertyChangeListener
pcl =
new PropertyChangeListener() {
264 public void propertyChange(PropertyChangeEvent evt) {
265 String eventType = evt.getPropertyName();
282 if (null != eventData
284 reviewStatusBus.post(eventData);
305 if (evt.getNewValue() == null) {
327 String accountTypesInUseQuery
328 =
"SELECT DISTINCT blackboard_attributes.value_text as account_type "
329 +
" FROM blackboard_artifacts "
330 +
" JOIN blackboard_attributes ON blackboard_artifacts.artifact_id = blackboard_attributes.artifact_id "
331 +
" WHERE blackboard_artifacts.artifact_type_id = " + BlackboardArtifact.ARTIFACT_TYPE.TSK_ACCOUNT.getTypeID()
332 +
" AND blackboard_attributes.attribute_type_id = " + BlackboardAttribute.ATTRIBUTE_TYPE.TSK_ACCOUNT_TYPE.getTypeID()
335 try (SleuthkitCase.CaseDbQuery executeQuery = skCase.executeQuery(accountTypesInUseQuery);
336 ResultSet resultSet = executeQuery.getResultSet()) {
337 while (resultSet.next()) {
338 String accountType = resultSet.getString(
"account_type");
339 list.add(accountType);
341 }
catch (TskCoreException | SQLException ex) {
342 LOGGER.log(Level.SEVERE,
"Error querying for account_types", ex);
351 if (Account.Type.CREDIT_CARD.getTypeName().equals(acountTypeName)) {
356 Account.Type accountType = skCase.getCommunicationsManager().getAccountType(acountTypeName);
358 }
catch (TskCoreException ex) {
359 LOGGER.log(Level.SEVERE,
"Error getting display name for account type. ", ex);
371 super.removeNotify();
393 private final PropertyChangeListener
pcl =
new PropertyChangeListener() {
395 public void propertyChange(PropertyChangeEvent evt) {
396 String eventType = evt.getPropertyName();
413 if (null != eventData
415 reviewStatusBus.post(eventData);
437 if (evt.getNewValue() == null) {
458 super.removeNotify();
464 =
"SELECT blackboard_artifacts.artifact_id "
465 +
" FROM blackboard_artifacts "
466 +
" JOIN blackboard_attributes ON blackboard_artifacts.artifact_id = blackboard_attributes.artifact_id "
467 +
" WHERE blackboard_artifacts.artifact_type_id = " + BlackboardArtifact.ARTIFACT_TYPE.TSK_ACCOUNT.getTypeID()
468 +
" AND blackboard_attributes.attribute_type_id = " + BlackboardAttribute.ATTRIBUTE_TYPE.TSK_ACCOUNT_TYPE.getTypeID()
469 +
" AND blackboard_attributes.value_text = '" +
accountType.getTypeName() +
"'"
472 try (SleuthkitCase.CaseDbQuery results = skCase.executeQuery(query);
473 ResultSet rs = results.getResultSet();) {
475 list.add(rs.getLong(
"artifact_id"));
477 }
catch (TskCoreException | SQLException ex) {
478 LOGGER.log(Level.SEVERE,
"Error querying for account artifacts.", ex);
488 }
catch (TskCoreException ex) {
489 LOGGER.log(Level.SEVERE,
"Error get black board artifact with id " + t, ex);
526 return visitor.
visit(
this);
531 return getClass().getName();
545 private final PropertyChangeListener pcl =
new PropertyChangeListener() {
547 public void propertyChange(PropertyChangeEvent evt) {
548 String eventType = evt.getPropertyName();
565 if (null != eventData
567 reviewStatusBus.post(eventData);
589 if (evt.getNewValue() == null) {
622 super.removeNotify();
629 protected boolean createKeys(List<CreditCardViewMode> list) {
658 super(Children.create(
new ViewModeFactory(),
true), Lookups.singleton(Account.Type.CREDIT_CARD.getDisplayName()));
659 setName(Account.Type.CREDIT_CARD.getDisplayName());
660 this.setIconBaseWithExtension(
"org/sleuthkit/autopsy/images/credit-cards.png");
670 return visitor.
visit(
this);
675 return getClass().getName();
681 private final PropertyChangeListener pcl =
new PropertyChangeListener() {
683 public void propertyChange(PropertyChangeEvent evt) {
684 String eventType = evt.getPropertyName();
701 if (null != eventData
703 reviewStatusBus.post(eventData);
725 if (evt.getNewValue() == null) {
746 super.removeNotify();
764 =
"SELECT blackboard_artifacts.obj_id,"
765 +
" solr_attribute.value_text AS solr_document_id, ";
766 if (skCase.getDatabaseType().equals(DbType.POSTGRESQL)) {
767 query +=
" string_agg(blackboard_artifacts.artifact_id::character varying, ',') AS artifact_IDs, "
768 +
" string_agg(blackboard_artifacts.review_status_id::character varying, ',') AS review_status_ids, ";
770 query +=
" GROUP_CONCAT(blackboard_artifacts.artifact_id) AS artifact_IDs, "
771 +
" GROUP_CONCAT(blackboard_artifacts.review_status_id) AS review_status_ids, ";
773 query +=
" COUNT( blackboard_artifacts.artifact_id) AS hits "
774 +
" FROM blackboard_artifacts "
775 +
" LEFT JOIN blackboard_attributes as solr_attribute ON blackboard_artifacts.artifact_id = solr_attribute.artifact_id "
776 +
" AND solr_attribute.attribute_type_id = " + BlackboardAttribute.ATTRIBUTE_TYPE.TSK_KEYWORD_SEARCH_DOCUMENT_ID.getTypeID()
777 +
" LEFT JOIN blackboard_attributes as account_type ON blackboard_artifacts.artifact_id = account_type.artifact_id "
778 +
" AND account_type.attribute_type_id = " + BlackboardAttribute.ATTRIBUTE_TYPE.TSK_ACCOUNT_TYPE.getTypeID()
779 +
" AND account_type.value_text = '" + Account.Type.CREDIT_CARD.getTypeName() +
"'"
780 +
" WHERE blackboard_artifacts.artifact_type_id = " + BlackboardArtifact.ARTIFACT_TYPE.TSK_ACCOUNT.getTypeID()
783 +
" GROUP BY blackboard_artifacts.obj_id, solr_document_id "
784 +
" ORDER BY hits DESC ";
785 try (SleuthkitCase.CaseDbQuery results = skCase.executeQuery(query);
786 ResultSet resultSet = results.getResultSet();) {
787 while (resultSet.next()) {
789 resultSet.getLong(
"obj_id"),
790 resultSet.getString(
"solr_document_id"),
791 unGroupConcat(resultSet.getString(
"artifact_IDs"), Long::valueOf),
792 resultSet.getLong(
"hits"),
793 new HashSet<>(unGroupConcat(resultSet.getString(
"review_status_ids"), reviewStatusID -> BlackboardArtifact.ReviewStatus.withID(Integer.valueOf(reviewStatusID))))));
795 }
catch (TskCoreException | SQLException ex) {
796 LOGGER.log(Level.SEVERE,
"Error querying for files with ccn hits.", ex);
806 List<Object> lookupContents =
new ArrayList<>();
808 lookupContents.add(skCase.getBlackboardArtifact(artId));
810 AbstractFile abstractFileById = skCase.getAbstractFileById(key.
getObjID());
811 lookupContents.add(abstractFileById);
812 return new Node[]{
new FileWithCCNNode(key, abstractFileById, lookupContents.toArray())};
813 }
catch (TskCoreException ex) {
814 LOGGER.log(Level.SEVERE,
"Error getting content for file with ccn hits.", ex);
833 this.setIconBaseWithExtension(
"org/sleuthkit/autopsy/images/file-icon.png");
834 reviewStatusBus.register(
this);
838 "# {0} - number of children",
839 "Accounts.ByFileNode.displayName=By File ({0})"})
842 =
"SELECT count(*) FROM ( SELECT count(*) AS documents "
843 +
" FROM blackboard_artifacts "
844 +
" LEFT JOIN blackboard_attributes as solr_attribute ON blackboard_artifacts.artifact_id = solr_attribute.artifact_id "
845 +
" AND solr_attribute.attribute_type_id = " + BlackboardAttribute.ATTRIBUTE_TYPE.TSK_KEYWORD_SEARCH_DOCUMENT_ID.getTypeID()
846 +
" LEFT JOIN blackboard_attributes as account_type ON blackboard_artifacts.artifact_id = account_type.artifact_id "
847 +
" AND account_type.attribute_type_id = " + BlackboardAttribute.ATTRIBUTE_TYPE.TSK_ACCOUNT_TYPE.getTypeID()
848 +
" AND account_type.value_text = '" + Account.Type.CREDIT_CARD.getTypeName() +
"'"
849 +
" WHERE blackboard_artifacts.artifact_type_id = " + BlackboardArtifact.ARTIFACT_TYPE.TSK_ACCOUNT.getTypeID()
852 +
" GROUP BY blackboard_artifacts.obj_id, solr_attribute.value_text ) AS foo";
853 try (SleuthkitCase.CaseDbQuery results = skCase.executeQuery(query);
854 ResultSet resultSet = results.getResultSet();) {
855 while (resultSet.next()) {
856 if (skCase.getDatabaseType().equals(DbType.POSTGRESQL)) {
857 setDisplayName(Bundle.Accounts_ByFileNode_displayName(resultSet.getLong(
"count")));
859 setDisplayName(Bundle.Accounts_ByFileNode_displayName(resultSet.getLong(
"count(*)")));
862 }
catch (TskCoreException | SQLException ex) {
863 LOGGER.log(Level.SEVERE,
"Error querying for files with ccn hits.", ex);
875 return visitor.
visit(
this);
880 return getClass().getName();
896 private final PropertyChangeListener pcl =
new PropertyChangeListener() {
898 public void propertyChange(PropertyChangeEvent evt) {
899 String eventType = evt.getPropertyName();
916 if (null != eventData
918 reviewStatusBus.post(eventData);
939 && (evt.getNewValue() == null)) {
960 super.removeNotify();
978 RangeMap<Integer, BinResult> binRanges = TreeRangeMap.create();
981 =
"SELECT SUBSTR(blackboard_attributes.value_text,1,8) AS BIN, "
982 +
" COUNT(blackboard_artifacts.artifact_id) AS count "
983 +
" FROM blackboard_artifacts "
984 +
" JOIN blackboard_attributes ON blackboard_artifacts.artifact_id = blackboard_attributes.artifact_id"
985 +
" WHERE blackboard_artifacts.artifact_type_id = " + BlackboardArtifact.ARTIFACT_TYPE.TSK_ACCOUNT.getTypeID()
986 +
" AND blackboard_attributes.attribute_type_id = " + BlackboardAttribute.ATTRIBUTE_TYPE.TSK_CARD_NUMBER.getTypeID()
991 try (SleuthkitCase.CaseDbQuery results = skCase.executeQuery(query);
992 ResultSet resultSet = results.getResultSet();) {
994 while (resultSet.next()) {
995 final Integer bin = Integer.valueOf(resultSet.getString(
"BIN"));
996 long count = resultSet.getLong(
"count");
999 BinResult previousResult = binRanges.get(bin);
1001 if (previousResult != null) {
1002 binRanges.remove(Range.closed(previousResult.getBINStart(), previousResult.getBINEnd()));
1003 count += previousResult.getCount();
1006 if (binRange == null) {
1007 binRanges.put(Range.closed(bin, bin),
new BinResult(count, bin, bin));
1012 binRanges.asMapOfRanges().values().forEach(list::add);
1013 }
catch (TskCoreException | SQLException ex) {
1014 LOGGER.log(Level.SEVERE,
"Error querying for BINs.", ex);
1022 return new Node[]{
new BINNode(key)};
1035 @NbBundle.Messages(
"Accounts.ByBINNode.name=By BIN")
1037 super(Children.create(
new BINFactory(),
true), Lookups.singleton(Bundle.Accounts_ByBINNode_name()));
1038 setName(Bundle.Accounts_ByBINNode_name());
1039 updateDisplayName();
1040 this.setIconBaseWithExtension(
"org/sleuthkit/autopsy/images/bank.png");
1041 reviewStatusBus.register(
this);
1044 @NbBundle.Messages({
1045 "# {0} - number of children",
1046 "Accounts.ByBINNode.displayName=By BIN ({0})"})
1049 =
"SELECT count(distinct SUBSTR(blackboard_attributes.value_text,1,8)) AS BINs "
1050 +
" FROM blackboard_artifacts "
1051 +
" JOIN blackboard_attributes ON blackboard_artifacts.artifact_id = blackboard_attributes.artifact_id"
1052 +
" WHERE blackboard_artifacts.artifact_type_id = " + BlackboardArtifact.ARTIFACT_TYPE.TSK_ACCOUNT.getTypeID()
1053 +
" AND blackboard_attributes.attribute_type_id = " + BlackboardAttribute.ATTRIBUTE_TYPE.TSK_CARD_NUMBER.getTypeID()
1056 try (SleuthkitCase.CaseDbQuery results = skCase.executeQuery(query);
1057 ResultSet resultSet = results.getResultSet();) {
1058 while (resultSet.next()) {
1059 setDisplayName(Bundle.Accounts_ByBINNode_displayName(resultSet.getLong(
"BINs")));
1061 }
catch (TskCoreException | SQLException ex) {
1062 LOGGER.log(Level.SEVERE,
"Error querying for BINs.", ex);
1073 return visitor.
visit(
this);
1078 return getClass().getName();
1083 updateDisplayName();
1088 updateDisplayName();
1102 hash = 79 * hash + (int) (this.objID ^ (this.objID >>> 32));
1103 hash = 79 * hash + Objects.hashCode(this.keywordSearchDocID);
1104 hash = 79 * hash + Objects.hashCode(this.artifactIDs);
1105 hash = 79 * hash + (int) (this.hits ^ (this.hits >>> 32));
1106 hash = 79 * hash + Objects.hashCode(this.statuses);
1118 if (getClass() != obj.getClass()) {
1122 if (this.objID != other.
objID) {
1125 if (this.hits != other.
hits) {
1131 if (!Objects.equals(
this.artifactIDs, other.
artifactIDs)) {
1134 if (!Objects.equals(
this.statuses, other.
statuses)) {
1144 private final Set<BlackboardArtifact.ReviewStatus>
statuses;
1146 private FileWithCCN(
long objID, String solrDocID, List<Long> artifactIDs,
long hits, Set<BlackboardArtifact.ReviewStatus> statuses) {
1148 this.keywordSearchDocID = solrDocID;
1149 this.artifactIDs = artifactIDs;
1151 this.statuses = statuses;
1170 return keywordSearchDocID;
1179 return Collections.unmodifiableList(artifactIDs);
1197 return Collections.unmodifiableSet(statuses);
1217 static <X> List<X> unGroupConcat(String groupConcat, Function<String, X> mapper) {
1218 return StringUtils.isBlank(groupConcat) ? Collections.emptyList()
1219 : Stream.of(groupConcat.split(
","))
1221 .collect(Collectors.toList());
1241 @NbBundle.Messages({
1242 "# {0} - raw file name",
1243 "# {1} - solr chunk id",
1244 "Accounts.FileWithCCNNode.unallocatedSpaceFile.displayName={0}_chunk_{1}"})
1246 super(Children.LEAF, Lookups.fixed(lookupContents));
1250 : Bundle.Accounts_FileWithCCNNode_unallocatedSpaceFile_displayName(content.getName(), StringUtils.substringAfter(key.
getkeywordSearchDocID(),
"_"));
1251 setName(fileName + key.
getObjID());
1252 setDisplayName(fileName);
1262 return visitor.
visit(
this);
1267 return getClass().getName();
1271 @NbBundle.Messages({
1272 "Accounts.FileWithCCNNode.nameProperty.displayName=File",
1273 "Accounts.FileWithCCNNode.accountsProperty.displayName=Accounts",
1274 "Accounts.FileWithCCNNode.statusProperty.displayName=Status",
1275 "Accounts.FileWithCCNNode.noDescription=no description"})
1277 Sheet sheet = super.createSheet();
1278 Sheet.Set propSet = sheet.get(Sheet.PROPERTIES);
1279 if (propSet == null) {
1280 propSet = Sheet.createPropertiesSet();
1284 propSet.put(
new NodeProperty<>(Bundle.Accounts_FileWithCCNNode_nameProperty_displayName(),
1285 Bundle.Accounts_FileWithCCNNode_nameProperty_displayName(),
1286 Bundle.Accounts_FileWithCCNNode_noDescription(),
1288 propSet.put(
new NodeProperty<>(Bundle.Accounts_FileWithCCNNode_accountsProperty_displayName(),
1289 Bundle.Accounts_FileWithCCNNode_accountsProperty_displayName(),
1290 Bundle.Accounts_FileWithCCNNode_noDescription(),
1292 propSet.put(
new NodeProperty<>(Bundle.Accounts_FileWithCCNNode_statusProperty_displayName(),
1293 Bundle.Accounts_FileWithCCNNode_statusProperty_displayName(),
1294 Bundle.Accounts_FileWithCCNNode_noDescription(),
1296 .map(BlackboardArtifact.ReviewStatus::getDisplayName)
1297 .collect(Collectors.joining(
", "))));
1304 Action[] actions = super.getActions(context);
1305 ArrayList<Action> arrayList =
new ArrayList<>();
1306 arrayList.addAll(Arrays.asList(actions));
1309 }
catch (TskCoreException ex) {
1310 LOGGER.log(Level.SEVERE,
"Error gettung content by id", ex);
1313 arrayList.add(approveActionInstance);
1314 arrayList.add(rejectActionInstance);
1316 return arrayList.toArray(
new Action[arrayList.size()]);
1344 =
"SELECT blackboard_artifacts.artifact_id "
1345 +
" FROM blackboard_artifacts "
1346 +
" JOIN blackboard_attributes ON blackboard_artifacts.artifact_id = blackboard_attributes.artifact_id "
1347 +
" WHERE blackboard_artifacts.artifact_type_id = " + BlackboardArtifact.ARTIFACT_TYPE.TSK_ACCOUNT.getTypeID()
1348 +
" AND blackboard_attributes.attribute_type_id = " + BlackboardAttribute.ATTRIBUTE_TYPE.TSK_CARD_NUMBER.getTypeID()
1349 +
" AND blackboard_attributes.value_text >= '" + bin.getBINStart() +
"' AND blackboard_attributes.value_text < '" + (bin.getBINEnd() + 1) +
"'"
1352 +
" ORDER BY blackboard_attributes.value_text";
1353 try (SleuthkitCase.CaseDbQuery results = skCase.executeQuery(query);
1354 ResultSet rs = results.getResultSet();) {
1356 list.add(rs.getLong(
"artifact_id"));
1358 }
catch (TskCoreException | SQLException ex) {
1359 LOGGER.log(Level.SEVERE,
"Error querying for account artifacts.", ex);
1367 if (skCase == null) {
1372 BlackboardArtifact art = skCase.getBlackboardArtifact(artifactID);
1374 }
catch (TskCoreException ex) {
1375 LOGGER.log(Level.SEVERE,
"Error creating BlackboardArtifactNode for artifact with ID " + artifactID, ex);
1382 if (bin.getBINStart() == bin.getBINEnd()) {
1383 return Integer.toString(bin.getBINStart());
1385 return bin.getBINStart() +
"-" + StringUtils.difference(bin.getBINStart() +
"", bin.getBINEnd() +
"");
1400 updateDisplayName();
1401 this.setIconBaseWithExtension(
"org/sleuthkit/autopsy/images/bank.png");
1402 reviewStatusBus.register(
this);
1407 updateDisplayName();
1413 updateDisplayName();
1418 =
"SELECT count(blackboard_artifacts.artifact_id ) AS count"
1419 +
" FROM blackboard_artifacts "
1420 +
" JOIN blackboard_attributes ON blackboard_artifacts.artifact_id = blackboard_attributes.artifact_id "
1421 +
" WHERE blackboard_artifacts.artifact_type_id = " + BlackboardArtifact.ARTIFACT_TYPE.TSK_ACCOUNT.getTypeID()
1422 +
" AND blackboard_attributes.attribute_type_id = " + BlackboardAttribute.ATTRIBUTE_TYPE.TSK_CARD_NUMBER.getTypeID()
1423 +
" AND blackboard_attributes.value_text >= '" + bin.getBINStart() +
"' AND blackboard_attributes.value_text < '" + (bin.getBINEnd() + 1) +
"'"
1426 try (SleuthkitCase.CaseDbQuery results = skCase.executeQuery(query);
1427 ResultSet resultSet = results.getResultSet();) {
1428 while (resultSet.next()) {
1429 setDisplayName(
getBinRangeString(bin) +
" (" + resultSet.getLong(
"count") +
")");
1431 }
catch (TskCoreException | SQLException ex) {
1432 LOGGER.log(Level.SEVERE,
"Error querying for account artifacts.", ex);
1445 return visitor.
visit(
this);
1450 return getClass().getName();
1454 Sheet.Set sheetSet = sheet.get(Sheet.PROPERTIES);
1455 if (sheetSet == null) {
1456 sheetSet = Sheet.createPropertiesSet();
1457 sheet.put(sheetSet);
1463 @NbBundle.Messages({
1464 "Accounts.BINNode.binProperty.displayName=Bank Identifier Number",
1465 "Accounts.BINNode.accountsProperty.displayName=Accounts",
1466 "Accounts.BINNode.cardTypeProperty.displayName=Payment Card Type",
1467 "Accounts.BINNode.schemeProperty.displayName=Credit Card Scheme",
1468 "Accounts.BINNode.brandProperty.displayName=Brand",
1469 "Accounts.BINNode.bankProperty.displayName=Bank",
1470 "Accounts.BINNode.bankCityProperty.displayName=Bank City",
1471 "Accounts.BINNode.bankCountryProperty.displayName=Bank Country",
1472 "Accounts.BINNode.bankPhoneProperty.displayName=Bank Phone #",
1473 "Accounts.BINNode.bankURLProperty.displayName=Bank URL",
1474 "Accounts.BINNode.noDescription=no description"})
1476 Sheet sheet = super.createSheet();
1477 Sheet.Set properties = getPropertySet(sheet);
1479 properties.put(
new NodeProperty<>(Bundle.Accounts_BINNode_binProperty_displayName(),
1480 Bundle.Accounts_BINNode_binProperty_displayName(),
1481 Bundle.Accounts_BINNode_noDescription(),
1483 properties.put(
new NodeProperty<>(Bundle.Accounts_BINNode_accountsProperty_displayName(),
1484 Bundle.Accounts_BINNode_accountsProperty_displayName(), Bundle.Accounts_BINNode_noDescription(),
1488 if (bin.hasDetails()) {
1489 bin.
getCardType().ifPresent(cardType -> properties.put(
new NodeProperty<>(Bundle.Accounts_BINNode_cardTypeProperty_displayName(),
1490 Bundle.Accounts_BINNode_cardTypeProperty_displayName(), Bundle.Accounts_BINNode_noDescription(),
1492 bin.
getScheme().ifPresent(scheme -> properties.put(
new NodeProperty<>(Bundle.Accounts_BINNode_schemeProperty_displayName(),
1493 Bundle.Accounts_BINNode_schemeProperty_displayName(), Bundle.Accounts_BINNode_noDescription(),
1495 bin.
getBrand().ifPresent(brand -> properties.put(
new NodeProperty<>(Bundle.Accounts_BINNode_brandProperty_displayName(),
1496 Bundle.Accounts_BINNode_brandProperty_displayName(), Bundle.Accounts_BINNode_noDescription(),
1498 bin.
getBankName().ifPresent(bankName -> properties.put(
new NodeProperty<>(Bundle.Accounts_BINNode_bankProperty_displayName(),
1499 Bundle.Accounts_BINNode_bankProperty_displayName(), Bundle.Accounts_BINNode_noDescription(),
1501 bin.
getBankCity().ifPresent(bankCity -> properties.put(
new NodeProperty<>(Bundle.Accounts_BINNode_bankCityProperty_displayName(),
1502 Bundle.Accounts_BINNode_bankCityProperty_displayName(), Bundle.Accounts_BINNode_noDescription(),
1504 bin.
getCountry().ifPresent(country -> properties.put(
new NodeProperty<>(Bundle.Accounts_BINNode_bankCountryProperty_displayName(),
1505 Bundle.Accounts_BINNode_bankCountryProperty_displayName(), Bundle.Accounts_BINNode_noDescription(),
1508 Bundle.Accounts_BINNode_bankPhoneProperty_displayName(), Bundle.Accounts_BINNode_noDescription(),
1510 bin.
getBankURL().ifPresent(url -> properties.put(
new NodeProperty<>(Bundle.Accounts_BINNode_bankURLProperty_displayName(),
1511 Bundle.Accounts_BINNode_bankURLProperty_displayName(), Bundle.Accounts_BINNode_noDescription(),
1518 this.setSheet(createSheet());
1533 hash = 97 * hash + this.binEnd;
1534 hash = 97 * hash + this.binStart;
1546 if (getClass() != obj.getClass()) {
1550 if (this.binEnd != other.
binEnd) {
1553 if (this.binStart != other.
binStart) {
1570 this.binRange = binRange;
1571 binStart = binRange.getBINstart();
1572 binEnd = binRange.getBINend();
1577 this.binRange = null;
1594 boolean hasDetails() {
1595 return binRange != null;
1649 super(artifact,
"org/sleuthkit/autopsy/images/credit-card.png");
1650 this.artifact = artifact;
1651 setName(Long.toString(
this.artifact.getArtifactID()));
1653 reviewStatusBus.register(
this);
1658 List<Action> actionsList =
new ArrayList<>();
1659 actionsList.addAll(Arrays.asList(super.getActions(context)));
1661 actionsList.add(approveActionInstance);
1662 actionsList.add(rejectActionInstance);
1664 return actionsList.toArray(
new Action[actionsList.size()]);
1669 Sheet sheet = super.createSheet();
1670 Sheet.Set properties = sheet.get(Sheet.PROPERTIES);
1671 if (properties == null) {
1672 properties = Sheet.createPropertiesSet();
1673 sheet.put(properties);
1675 properties.put(
new NodeProperty<>(Bundle.Accounts_FileWithCCNNode_statusProperty_displayName(),
1676 Bundle.Accounts_FileWithCCNNode_statusProperty_displayName(),
1677 Bundle.Accounts_FileWithCCNNode_noDescription(),
1678 artifact.getReviewStatus().getDisplayName()));
1687 event.artifacts.stream().filter((art) -> (art.getArtifactID() == this.artifact.getArtifactID())).map((_item) -> {
1689 }).forEachOrdered((_item) -> {
1695 this.setSheet(createSheet());
1703 @NbBundle.Messages(
"ToggleShowRejected.name=Show Rejected Results")
1705 super(Bundle.ToggleShowRejected_name());
1731 this.newStatus = newStatus;
1742 List<String[]> selectedPaths = Utilities.actionsGlobalContext().lookupAll(Node.class).stream()
1744 String[] createPath;
1750 if (newStatus == BlackboardArtifact.ReviewStatus.REJECTED && showRejected ==
false) {
1751 List<Node> siblings = Arrays.asList(node.getParentNode().getChildren().getNodes());
1752 if (siblings.size() > 1) {
1753 int indexOf = siblings.indexOf(node);
1755 Node sibling = indexOf > 0
1756 ? siblings.get(indexOf - 1)
1757 : siblings.get(Integer.max(indexOf + 1, siblings.size() - 1));
1758 createPath = NodeOp.createPath(sibling, null);
1768 createPath = NodeOp.createPath(node, null);
1771 return Arrays.copyOfRange(createPath, 1, createPath.length);
1773 .filter(Objects::nonNull)
1774 .collect(Collectors.toList());
1777 final Collection<? extends BlackboardArtifact> artifacts = Utilities.actionsGlobalContext().lookupAll(BlackboardArtifact.class);
1778 artifacts.forEach(artifact -> {
1780 artifact.setReviewStatus(newStatus);
1781 }
catch (TskCoreException ex) {
1782 LOGGER.log(Level.SEVERE,
"Error changing artifact review status.", ex);
1786 reviewStatusBus.post(
new ReviewStatusChangeEvent(artifacts, newStatus));
1788 final DataResultTopComponent directoryListing = DirectoryTreeTopComponent.findInstance().getDirectoryListing();
1789 final Node rootNode = directoryListing.getRootNode();
1792 List<Node> toArray =
new ArrayList<>();
1793 selectedPaths.forEach(path -> {
1795 toArray.add(NodeOp.findPath(rootNode, path));
1796 }
catch (NodeNotFoundException ex) {
1801 directoryListing.setSelectedNodes(toArray.toArray(
new Node[toArray.size()]));
1807 @NbBundle.Messages({
"ApproveAccountsAction.name=Approve Accounts"})
1809 super(Bundle.ApproveAccountsAction_name(), BlackboardArtifact.ReviewStatus.APPROVED);
1815 @NbBundle.Messages({
"RejectAccountsAction.name=Reject Accounts"})
1817 super(Bundle.RejectAccountsAction_name(), BlackboardArtifact.ReviewStatus.REJECTED);
1823 Collection<? extends BlackboardArtifact> artifacts;
1824 BlackboardArtifact.ReviewStatus newReviewStatus;
1826 ReviewStatusChangeEvent(Collection<? extends BlackboardArtifact> artifacts, BlackboardArtifact.ReviewStatus newReviewStatus) {
1827 this.artifacts = artifacts;
1828 this.newReviewStatus = newReviewStatus;
1839 if (type.equals(Account.Type.CREDIT_CARD)) {
1840 return ICON_BASE_PATH +
"credit-card.png";
1841 }
else if (type.equals(Account.Type.DEVICE)) {
1842 return ICON_BASE_PATH +
"image.png";
1843 }
else if (type.equals(Account.Type.EMAIL)) {
1844 return ICON_BASE_PATH +
"email.png";
1845 }
else if (type.equals(Account.Type.FACEBOOK)) {
1846 return ICON_BASE_PATH +
"facebook.png";
1847 }
else if (type.equals(Account.Type.INSTAGRAM)) {
1848 return ICON_BASE_PATH +
"instagram.png";
1849 }
else if (type.equals(Account.Type.MESSAGING_APP)) {
1850 return ICON_BASE_PATH +
"messaging.png";
1851 }
else if (type.equals(Account.Type.PHONE)) {
1852 return ICON_BASE_PATH +
"phone.png";
1853 }
else if (type.equals(Account.Type.TWITTER)) {
1854 return ICON_BASE_PATH +
"twitter.png";
1855 }
else if (type.equals(Account.Type.WEBSITE)) {
1856 return ICON_BASE_PATH +
"web-file.png";
1857 }
else if (type.equals(Account.Type.WHATSAPP)) {
1858 return ICON_BASE_PATH +
"WhatsApp.png";
1861 return ICON_BASE_PATH +
"face.png";
CreditCardNumberFactory(BinResult bin)
static final Set< IngestManager.IngestModuleEvent > INGEST_MODULE_EVENTS_OF_INTEREST
final BlackboardArtifact.ReviewStatus newStatus
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 RejectAccounts rejectActionInstance
List< Long > getArtifactIDs()
boolean createKeys(List< String > list)
abstract boolean createKeys(List< X > list)
AccountArtifactNode(BlackboardArtifact artifact)
static synchronized BankIdentificationNumber getBINInfo(int bin)
Node[] createNodesForKey(Long artifactID)
Action[] getActions(boolean context)
Node[] createNodesForKey(FileWithCCN key)
static String getIconFilePath(Account.Type type)
boolean createKeys(List< FileWithCCN > list)
final Account.Type accountType
Optional< String > getBankURL()
boolean createKeys(List< Long > list)
final ApproveAccounts approveActionInstance
final long filteringDSObjId
T visit(DataSourcesNode in)
Node[] createNodesForKey(CreditCardViewMode key)
void removeIngestJobEventListener(final PropertyChangeListener listener)
Optional< String > getScheme()
final Set< BlackboardArtifact.ReviewStatus > statuses
Optional< String > getBrand()
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()
Node[] createNodesForKey(String acountTypeName)
boolean createKeys(List< Long > list)
FileWithCCNNode(FileWithCCN key, Content content, Object[] lookupContents)
Action[] getActions(boolean context)
final List< Long > artifactIDs
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 PropertyChangeListener pcl
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)