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)