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;
 
   79 import org.
sleuthkit.datamodel.BlackboardArtifact.ARTIFACT_TYPE;
 
   93     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();
 
  124     public Accounts(SleuthkitCase skCase, 
long objId) {
 
  126         this.datasourceObjId = objId;
 
  135         return visitor.
visit(
this);
 
  146         return showRejected ? 
" " : 
" AND blackboard_artifacts.review_status_id != " + BlackboardArtifact.ReviewStatus.REJECTED.getID() + 
" "; 
 
  157             return "  AND blackboard_artifacts.data_source_obj_id = " + datasourceObjId + 
" ";
 
  195         abstract protected boolean createKeys(List<X> list);
 
  210             super.removeNotify();
 
  225     @NbBundle.Messages({
"Accounts.RootNode.displayName=Accounts"})
 
  231             setDisplayName(Bundle.Accounts_RootNode_displayName());
 
  232             this.setIconBaseWithExtension(
"org/sleuthkit/autopsy/images/accounts.png");    
 
  242             return visitor.
visit(
this);
 
  247             return getClass().getName();
 
  260         private final PropertyChangeListener 
pcl = 
new PropertyChangeListener() {
 
  262             public void propertyChange(PropertyChangeEvent evt) {
 
  263                 String eventType = evt.getPropertyName();
 
  280                         if (null != eventData
 
  282                             reviewStatusBus.post(eventData);
 
  303                     if (evt.getNewValue() == null) {
 
  325             String  accountTypesInUseQuery =   
 
  326                    "SELECT DISTINCT blackboard_attributes.value_text as account_type " 
  327                     + 
" FROM blackboard_artifacts "  
  328                     + 
"      JOIN blackboard_attributes ON blackboard_artifacts.artifact_id = blackboard_attributes.artifact_id "  
  329                     + 
" WHERE blackboard_attributes.attribute_type_id = " + BlackboardAttribute.ATTRIBUTE_TYPE.TSK_ACCOUNT_TYPE.getTypeID()
 
  332             try (SleuthkitCase.CaseDbQuery executeQuery = skCase.executeQuery(accountTypesInUseQuery );
 
  333                     ResultSet resultSet = executeQuery.getResultSet()) {
 
  334                 while (resultSet.next()) {
 
  335                     String accountType = resultSet.getString(
"account_type");
 
  336                     list.add(accountType);
 
  338             } 
catch (TskCoreException | SQLException ex) {
 
  339                 LOGGER.log(Level.SEVERE, 
"Error querying for account_types", ex);
 
  348             if (Account.Type.CREDIT_CARD.getTypeName().equals(acountTypeName)) {
 
  353                     Account.Type accountType = skCase.getCommunicationsManager().getAccountType(acountTypeName);
 
  355                 } 
catch (TskCoreException ex) {
 
  356                     LOGGER.log(Level.SEVERE, 
"Error getting display name for account type. ", ex);
 
  368             super.removeNotify();
 
  390         private final PropertyChangeListener 
pcl = 
new PropertyChangeListener() {
 
  392             public void propertyChange(PropertyChangeEvent evt) {
 
  393                 String eventType = evt.getPropertyName();
 
  410                         if (null != eventData
 
  412                             reviewStatusBus.post(eventData);
 
  434                     if (evt.getNewValue() == null) {
 
  455             super.removeNotify();
 
  461                     "SELECT blackboard_artifacts.artifact_id "  
  462                     + 
" FROM blackboard_artifacts "  
  463                     + 
"      JOIN blackboard_attributes ON blackboard_artifacts.artifact_id = blackboard_attributes.artifact_id "  
  464                     + 
" WHERE blackboard_artifacts.artifact_type_id = " + BlackboardArtifact.ARTIFACT_TYPE.TSK_ACCOUNT.getTypeID() 
 
  465                     + 
"     AND blackboard_attributes.attribute_type_id = " + BlackboardAttribute.ATTRIBUTE_TYPE.TSK_ACCOUNT_TYPE.getTypeID() 
 
  466                     + 
"     AND blackboard_attributes.value_text = '" + 
accountType.getTypeName() + 
"'"  
  469             try (SleuthkitCase.CaseDbQuery results = skCase.executeQuery(query);
 
  470                     ResultSet rs = results.getResultSet();) {
 
  472                     list.add(rs.getLong(
"artifact_id")); 
 
  474             } 
catch (TskCoreException | SQLException ex) {
 
  475                 LOGGER.log(Level.SEVERE, 
"Error querying for account artifacts.", ex); 
 
  485             } 
catch (TskCoreException ex) {
 
  486                 LOGGER.log(Level.SEVERE, 
"Error get black board artifact with id " + t, ex);
 
  523             return visitor.
visit(
this);
 
  528             return getClass().getName();
 
  542         private final PropertyChangeListener pcl = 
new PropertyChangeListener() {
 
  544             public void propertyChange(PropertyChangeEvent evt) {
 
  545                 String eventType = evt.getPropertyName();
 
  562                         if (null != eventData
 
  564                             reviewStatusBus.post(eventData);
 
  586                     if (evt.getNewValue() == null) {
 
  619             super.removeNotify();
 
  626         protected boolean createKeys(List<CreditCardViewMode> list) {
 
  655             super(Children.create(
new ViewModeFactory(), 
true), Lookups.singleton(Account.Type.CREDIT_CARD.getDisplayName()));
 
  656             setName(Account.Type.CREDIT_CARD.getDisplayName());
 
  657             this.setIconBaseWithExtension(
"org/sleuthkit/autopsy/images/credit-cards.png");   
 
  667             return visitor.
visit(
this);
 
  672             return getClass().getName();
 
  678         private final PropertyChangeListener pcl = 
new PropertyChangeListener() {
 
  680             public void propertyChange(PropertyChangeEvent evt) {
 
  681                 String eventType = evt.getPropertyName();
 
  698                         if (null != eventData
 
  700                             reviewStatusBus.post(eventData);
 
  722                     if (evt.getNewValue() == null) {
 
  743             super.removeNotify();
 
  761                     "SELECT blackboard_artifacts.obj_id,"  
  762                     + 
"      solr_attribute.value_text AS solr_document_id, "; 
 
  763             if (skCase.getDatabaseType().equals(DbType.POSTGRESQL)) {
 
  764                 query += 
"      string_agg(blackboard_artifacts.artifact_id::character varying, ',') AS artifact_IDs, "  
  765                         + 
"      string_agg(blackboard_artifacts.review_status_id::character varying, ',') AS review_status_ids, ";
 
  767                 query += 
"      GROUP_CONCAT(blackboard_artifacts.artifact_id) AS artifact_IDs, "  
  768                         + 
"      GROUP_CONCAT(blackboard_artifacts.review_status_id) AS review_status_ids, ";
 
  770             query += 
"      COUNT( blackboard_artifacts.artifact_id) AS hits  "  
  771                     + 
" FROM blackboard_artifacts "  
  772                     + 
" LEFT JOIN blackboard_attributes as solr_attribute ON blackboard_artifacts.artifact_id = solr_attribute.artifact_id "  
  773                     + 
"                                AND solr_attribute.attribute_type_id = " + BlackboardAttribute.ATTRIBUTE_TYPE.TSK_KEYWORD_SEARCH_DOCUMENT_ID.getTypeID() 
 
  774                     + 
" LEFT JOIN blackboard_attributes as account_type ON blackboard_artifacts.artifact_id = account_type.artifact_id "  
  775                     + 
"                                AND account_type.attribute_type_id = " + BlackboardAttribute.ATTRIBUTE_TYPE.TSK_ACCOUNT_TYPE.getTypeID() 
 
  776                     + 
"                                AND account_type.value_text = '" + Account.Type.CREDIT_CARD.getTypeName() + 
"'"  
  777                     + 
" WHERE blackboard_artifacts.artifact_type_id = " + BlackboardArtifact.ARTIFACT_TYPE.TSK_ACCOUNT.getTypeID() 
 
  780                     + 
" GROUP BY blackboard_artifacts.obj_id, solr_document_id "  
  781                     + 
" ORDER BY hits DESC ";  
 
  782             try (SleuthkitCase.CaseDbQuery results = skCase.executeQuery(query);
 
  783                     ResultSet resultSet = results.getResultSet();) {
 
  784                 while (resultSet.next()) {
 
  786                             resultSet.getLong(
"obj_id"), 
 
  787                             resultSet.getString(
"solr_document_id"), 
 
  788                             unGroupConcat(resultSet.getString(
"artifact_IDs"), Long::valueOf), 
 
  789                             resultSet.getLong(
"hits"), 
 
  790                             new HashSet<>(unGroupConcat(resultSet.getString(
"review_status_ids"), reviewStatusID -> BlackboardArtifact.ReviewStatus.withID(Integer.valueOf(reviewStatusID))))));  
 
  792             } 
catch (TskCoreException | SQLException ex) {
 
  793                 LOGGER.log(Level.SEVERE, 
"Error querying for files with ccn hits.", ex); 
 
  803                 List<Object> lookupContents = 
new ArrayList<>();
 
  805                     lookupContents.add(skCase.getBlackboardArtifact(artId));
 
  807                 AbstractFile abstractFileById = skCase.getAbstractFileById(key.
getObjID());
 
  808                 lookupContents.add(abstractFileById);
 
  809                 return new Node[]{
new FileWithCCNNode(key, abstractFileById, lookupContents.toArray())};
 
  810             } 
catch (TskCoreException ex) {
 
  811                 LOGGER.log(Level.SEVERE, 
"Error getting content for file with ccn hits.", ex); 
 
  830             this.setIconBaseWithExtension(
"org/sleuthkit/autopsy/images/file-icon.png");   
 
  831             reviewStatusBus.register(
this);
 
  835             "# {0} - number of children",
 
  836             "Accounts.ByFileNode.displayName=By File ({0})"})
 
  839                     "SELECT count(*) FROM ( SELECT count(*) AS documents " 
  840                     + 
" FROM blackboard_artifacts "  
  841                     + 
" LEFT JOIN blackboard_attributes as solr_attribute ON blackboard_artifacts.artifact_id = solr_attribute.artifact_id "  
  842                     + 
"                                AND solr_attribute.attribute_type_id = " + BlackboardAttribute.ATTRIBUTE_TYPE.TSK_KEYWORD_SEARCH_DOCUMENT_ID.getTypeID() 
 
  843                     + 
" LEFT JOIN blackboard_attributes as account_type ON blackboard_artifacts.artifact_id = account_type.artifact_id "  
  844                     + 
"                                AND account_type.attribute_type_id = " + BlackboardAttribute.ATTRIBUTE_TYPE.TSK_ACCOUNT_TYPE.getTypeID() 
 
  845                     + 
"                                AND account_type.value_text = '" + Account.Type.CREDIT_CARD.getTypeName() + 
"'"  
  846                     + 
" WHERE blackboard_artifacts.artifact_type_id = " + BlackboardArtifact.ARTIFACT_TYPE.TSK_ACCOUNT.getTypeID() 
 
  849                     + 
" GROUP BY blackboard_artifacts.obj_id, solr_attribute.value_text ) AS foo";
 
  850             try (SleuthkitCase.CaseDbQuery results = skCase.executeQuery(query);
 
  851                     ResultSet resultSet = results.getResultSet();) {
 
  852                 while (resultSet.next()) {
 
  853                     if (skCase.getDatabaseType().equals(DbType.POSTGRESQL)) {
 
  854                         setDisplayName(Bundle.Accounts_ByFileNode_displayName(resultSet.getLong(
"count")));
 
  856                         setDisplayName(Bundle.Accounts_ByFileNode_displayName(resultSet.getLong(
"count(*)")));
 
  859             } 
catch (TskCoreException | SQLException ex) {
 
  860                 LOGGER.log(Level.SEVERE, 
"Error querying for files with ccn hits.", ex); 
 
  872             return visitor.
visit(
this);
 
  877             return getClass().getName();
 
  893         private final PropertyChangeListener pcl = 
new PropertyChangeListener() {
 
  895             public void propertyChange(PropertyChangeEvent evt) {
 
  896                 String eventType = evt.getPropertyName();
 
  913                         if (null != eventData
 
  915                             reviewStatusBus.post(eventData);
 
  936                         && (evt.getNewValue() == null)) {
 
  957             super.removeNotify();
 
  975             RangeMap<Integer, BinResult> binRanges = TreeRangeMap.create();
 
  978                     "SELECT SUBSTR(blackboard_attributes.value_text,1,8) AS BIN, "  
  979                     + 
"     COUNT(blackboard_artifacts.artifact_id) AS count "  
  980                     + 
" FROM blackboard_artifacts "  
  981                     + 
"      JOIN blackboard_attributes ON blackboard_artifacts.artifact_id = blackboard_attributes.artifact_id"  
  982                     + 
" WHERE blackboard_artifacts.artifact_type_id = " + BlackboardArtifact.ARTIFACT_TYPE.TSK_ACCOUNT.getTypeID() 
 
  983                     + 
"     AND blackboard_attributes.attribute_type_id = " + BlackboardAttribute.ATTRIBUTE_TYPE.TSK_CARD_NUMBER.getTypeID() 
 
  988             try (SleuthkitCase.CaseDbQuery results = skCase.executeQuery(query);
 
  989                     ResultSet resultSet = results.getResultSet();) {
 
  991                 while (resultSet.next()) {
 
  992                     final Integer bin = Integer.valueOf(resultSet.getString(
"BIN"));
 
  993                     long count = resultSet.getLong(
"count");
 
  996                     BinResult previousResult = binRanges.get(bin);
 
  998                     if (previousResult != null) {
 
  999                         binRanges.remove(Range.closed(previousResult.getBINStart(), previousResult.getBINEnd()));
 
 1000                         count += previousResult.getCount();
 
 1003                     if (binRange == null) {
 
 1004                         binRanges.put(Range.closed(bin, bin), 
new BinResult(count, bin, bin));
 
 1009                 binRanges.asMapOfRanges().values().forEach(list::add);
 
 1010             } 
catch (TskCoreException | SQLException ex) {
 
 1011                 LOGGER.log(Level.SEVERE, 
"Error querying for BINs.", ex); 
 
 1019             return new Node[]{
new BINNode(key)};
 
 1032         @NbBundle.Messages(
"Accounts.ByBINNode.name=By BIN")
 
 1034             super(Children.create(
new BINFactory(), 
true), Lookups.singleton(Bundle.Accounts_ByBINNode_name()));
 
 1035             setName(Bundle.Accounts_ByBINNode_name());  
 
 1036             updateDisplayName();
 
 1037             this.setIconBaseWithExtension(
"org/sleuthkit/autopsy/images/bank.png");   
 
 1038             reviewStatusBus.register(
this);
 
 1041         @NbBundle.Messages({
 
 1042             "# {0} - number of children",
 
 1043             "Accounts.ByBINNode.displayName=By BIN ({0})"})
 
 1046                     "SELECT count(distinct SUBSTR(blackboard_attributes.value_text,1,8)) AS BINs "  
 1047                     + 
" FROM blackboard_artifacts "  
 1048                     + 
"      JOIN blackboard_attributes ON blackboard_artifacts.artifact_id = blackboard_attributes.artifact_id"  
 1049                     + 
" WHERE blackboard_artifacts.artifact_type_id = " + BlackboardArtifact.ARTIFACT_TYPE.TSK_ACCOUNT.getTypeID() 
 
 1050                     + 
"     AND blackboard_attributes.attribute_type_id = " + BlackboardAttribute.ATTRIBUTE_TYPE.TSK_CARD_NUMBER.getTypeID() 
 
 1053             try (SleuthkitCase.CaseDbQuery results = skCase.executeQuery(query);
 
 1054                     ResultSet resultSet = results.getResultSet();) {
 
 1055                 while (resultSet.next()) {
 
 1056                     setDisplayName(Bundle.Accounts_ByBINNode_displayName(resultSet.getLong(
"BINs")));
 
 1058             } 
catch (TskCoreException | SQLException ex) {
 
 1059                 LOGGER.log(Level.SEVERE, 
"Error querying for BINs.", ex); 
 
 1070             return visitor.
visit(
this);
 
 1075             return getClass().getName();
 
 1080             updateDisplayName();
 
 1085             updateDisplayName();
 
 1099             hash = 79 * hash + (int) (this.objID ^ (this.objID >>> 32));
 
 1100             hash = 79 * hash + Objects.hashCode(this.keywordSearchDocID);
 
 1101             hash = 79 * hash + Objects.hashCode(this.artifactIDs);
 
 1102             hash = 79 * hash + (int) (this.hits ^ (this.hits >>> 32));
 
 1103             hash = 79 * hash + Objects.hashCode(this.statuses);
 
 1115             if (getClass() != obj.getClass()) {
 
 1119             if (this.objID != other.
objID) {
 
 1122             if (this.hits != other.
hits) {
 
 1128             if (!Objects.equals(
this.artifactIDs, other.
artifactIDs)) {
 
 1131             if (!Objects.equals(
this.statuses, other.
statuses)) {
 
 1141         private final Set<BlackboardArtifact.ReviewStatus> 
statuses;
 
 1143         private FileWithCCN(
long objID, String solrDocID, List<Long> artifactIDs, 
long hits, Set<BlackboardArtifact.ReviewStatus> statuses) {
 
 1145             this.keywordSearchDocID = solrDocID;
 
 1146             this.artifactIDs = artifactIDs;
 
 1148             this.statuses = statuses;
 
 1167             return keywordSearchDocID;
 
 1214     static <X> List<X> unGroupConcat(String groupConcat, Function<String, X> mapper) {
 
 1215         return StringUtils.isBlank(groupConcat) ? Collections.emptyList()
 
 1216                 : Stream.of(groupConcat.split(
",")) 
 
 1218                         .collect(Collectors.toList());
 
 1238         @NbBundle.Messages({
 
 1239             "# {0} - raw file name",
 
 1240             "# {1} - solr chunk id",
 
 1241             "Accounts.FileWithCCNNode.unallocatedSpaceFile.displayName={0}_chunk_{1}"})
 
 1243             super(Children.LEAF, Lookups.fixed(lookupContents));
 
 1247                     : Bundle.Accounts_FileWithCCNNode_unallocatedSpaceFile_displayName(content.getName(), StringUtils.substringAfter(key.
getkeywordSearchDocID(), 
"_")); 
 
 1248             setName(fileName + key.
getObjID());
 
 1249             setDisplayName(fileName);
 
 1259             return visitor.
visit(
this);
 
 1264             return getClass().getName();
 
 1268         @NbBundle.Messages({
 
 1269             "Accounts.FileWithCCNNode.nameProperty.displayName=File",
 
 1270             "Accounts.FileWithCCNNode.accountsProperty.displayName=Accounts",
 
 1271             "Accounts.FileWithCCNNode.statusProperty.displayName=Status",
 
 1272             "Accounts.FileWithCCNNode.noDescription=no description"})
 
 1274             Sheet sheet = super.createSheet();
 
 1275             Sheet.Set propSet = sheet.get(Sheet.PROPERTIES);
 
 1276             if (propSet == null) {
 
 1277                 propSet = Sheet.createPropertiesSet();
 
 1281             propSet.put(
new NodeProperty<>(Bundle.Accounts_FileWithCCNNode_nameProperty_displayName(),
 
 1282                     Bundle.Accounts_FileWithCCNNode_nameProperty_displayName(),
 
 1283                     Bundle.Accounts_FileWithCCNNode_noDescription(),
 
 1285             propSet.put(
new NodeProperty<>(Bundle.Accounts_FileWithCCNNode_accountsProperty_displayName(),
 
 1286                     Bundle.Accounts_FileWithCCNNode_accountsProperty_displayName(),
 
 1287                     Bundle.Accounts_FileWithCCNNode_noDescription(),
 
 1289             propSet.put(
new NodeProperty<>(Bundle.Accounts_FileWithCCNNode_statusProperty_displayName(),
 
 1290                     Bundle.Accounts_FileWithCCNNode_statusProperty_displayName(),
 
 1291                     Bundle.Accounts_FileWithCCNNode_noDescription(),
 
 1293                             .map(BlackboardArtifact.ReviewStatus::getDisplayName)
 
 1294                             .collect(Collectors.joining(
", ")))); 
 
 1301             Action[] actions = super.getActions(context);
 
 1302             ArrayList<Action> arrayList = 
new ArrayList<>();
 
 1303             arrayList.addAll(Arrays.asList(actions));
 
 1306             } 
catch (TskCoreException ex) {
 
 1307                 LOGGER.log(Level.SEVERE, 
"Error gettung content by id", ex);
 
 1310             arrayList.add(approveActionInstance);
 
 1311             arrayList.add(rejectActionInstance);
 
 1313             return arrayList.toArray(
new Action[arrayList.size()]);
 
 1341                     "SELECT blackboard_artifacts.artifact_id "  
 1342                     + 
" FROM blackboard_artifacts "  
 1343                     + 
"      JOIN blackboard_attributes ON blackboard_artifacts.artifact_id = blackboard_attributes.artifact_id "  
 1344                     + 
" WHERE blackboard_artifacts.artifact_type_id = " + BlackboardArtifact.ARTIFACT_TYPE.TSK_ACCOUNT.getTypeID() 
 
 1345                     + 
"     AND blackboard_attributes.attribute_type_id = " + BlackboardAttribute.ATTRIBUTE_TYPE.TSK_CARD_NUMBER.getTypeID() 
 
 1346                     + 
"     AND blackboard_attributes.value_text >= '" + bin.getBINStart() + 
"' AND  blackboard_attributes.value_text < '" + (bin.getBINEnd() + 1) + 
"'"  
 1349                     + 
" ORDER BY blackboard_attributes.value_text"; 
 
 1350             try (SleuthkitCase.CaseDbQuery results = skCase.executeQuery(query);
 
 1351                     ResultSet rs = results.getResultSet();) {
 
 1353                     list.add(rs.getLong(
"artifact_id")); 
 
 1355             } 
catch (TskCoreException | SQLException ex) {
 
 1356                 LOGGER.log(Level.SEVERE, 
"Error querying for account artifacts.", ex); 
 
 1364             if (skCase == null) {
 
 1369                 BlackboardArtifact art = skCase.getBlackboardArtifact(artifactID);
 
 1371             } 
catch (TskCoreException ex) {
 
 1372                 LOGGER.log(Level.SEVERE, 
"Error creating BlackboardArtifactNode for artifact with ID " + artifactID, ex);   
 
 1379         if (bin.getBINStart() == bin.getBINEnd()) {
 
 1380             return Integer.toString(bin.getBINStart());
 
 1382             return bin.getBINStart() + 
"-" + StringUtils.difference(bin.getBINStart() + 
"", bin.getBINEnd() + 
"");
 
 1395             updateDisplayName();
 
 1396             this.setIconBaseWithExtension(
"org/sleuthkit/autopsy/images/bank.png");   
 
 1397             reviewStatusBus.register(
this);
 
 1402             updateDisplayName();
 
 1408             updateDisplayName();
 
 1413                     "SELECT count(blackboard_artifacts.artifact_id ) AS count"  
 1414                     + 
" FROM blackboard_artifacts "  
 1415                     + 
"      JOIN blackboard_attributes ON blackboard_artifacts.artifact_id = blackboard_attributes.artifact_id "  
 1416                     + 
" WHERE blackboard_artifacts.artifact_type_id = " + BlackboardArtifact.ARTIFACT_TYPE.TSK_ACCOUNT.getTypeID() 
 
 1417                     + 
"     AND blackboard_attributes.attribute_type_id = " + BlackboardAttribute.ATTRIBUTE_TYPE.TSK_CARD_NUMBER.getTypeID() 
 
 1418                     + 
"     AND blackboard_attributes.value_text >= '" + bin.getBINStart() + 
"' AND  blackboard_attributes.value_text < '" + (bin.getBINEnd() + 1) + 
"'"  
 1421             try (SleuthkitCase.CaseDbQuery results = skCase.executeQuery(query);
 
 1422                     ResultSet resultSet = results.getResultSet();) {
 
 1423                 while (resultSet.next()) {
 
 1424                     setDisplayName(
getBinRangeString(bin) + 
" (" + resultSet.getLong(
"count") + 
")"); 
 
 1426             } 
catch (TskCoreException | SQLException ex) {
 
 1427                 LOGGER.log(Level.SEVERE, 
"Error querying for account artifacts.", ex); 
 
 1440             return visitor.
visit(
this);
 
 1445             return getClass().getName();
 
 1449             Sheet.Set sheetSet = sheet.get(Sheet.PROPERTIES);
 
 1450             if (sheetSet == null) {
 
 1451                 sheetSet = Sheet.createPropertiesSet();
 
 1452                 sheet.put(sheetSet);
 
 1458         @NbBundle.Messages({
 
 1459             "Accounts.BINNode.binProperty.displayName=Bank Identifier Number",
 
 1460             "Accounts.BINNode.accountsProperty.displayName=Accounts",
 
 1461             "Accounts.BINNode.cardTypeProperty.displayName=Payment Card Type",
 
 1462             "Accounts.BINNode.schemeProperty.displayName=Credit Card Scheme",
 
 1463             "Accounts.BINNode.brandProperty.displayName=Brand",
 
 1464             "Accounts.BINNode.bankProperty.displayName=Bank",
 
 1465             "Accounts.BINNode.bankCityProperty.displayName=Bank City",
 
 1466             "Accounts.BINNode.bankCountryProperty.displayName=Bank Country",
 
 1467             "Accounts.BINNode.bankPhoneProperty.displayName=Bank Phone #",
 
 1468             "Accounts.BINNode.bankURLProperty.displayName=Bank URL",
 
 1469             "Accounts.BINNode.noDescription=no description"})
 
 1471             Sheet sheet = super.createSheet();
 
 1472             Sheet.Set properties = getPropertySet(sheet);
 
 1474             properties.put(
new NodeProperty<>(Bundle.Accounts_BINNode_binProperty_displayName(),
 
 1475                     Bundle.Accounts_BINNode_binProperty_displayName(),
 
 1476                     Bundle.Accounts_BINNode_noDescription(),
 
 1478             properties.put(
new NodeProperty<>(Bundle.Accounts_BINNode_accountsProperty_displayName(),
 
 1479                     Bundle.Accounts_BINNode_accountsProperty_displayName(), Bundle.Accounts_BINNode_noDescription(),
 
 1483             if (bin.hasDetails()) {
 
 1484                 bin.
getCardType().ifPresent(cardType -> properties.put(
new NodeProperty<>(Bundle.Accounts_BINNode_cardTypeProperty_displayName(),
 
 1485                         Bundle.Accounts_BINNode_cardTypeProperty_displayName(), Bundle.Accounts_BINNode_noDescription(),
 
 1487                 bin.
getScheme().ifPresent(scheme -> properties.put(
new NodeProperty<>(Bundle.Accounts_BINNode_schemeProperty_displayName(),
 
 1488                         Bundle.Accounts_BINNode_schemeProperty_displayName(), Bundle.Accounts_BINNode_noDescription(),
 
 1490                 bin.
getBrand().ifPresent(brand -> properties.put(
new NodeProperty<>(Bundle.Accounts_BINNode_brandProperty_displayName(),
 
 1491                         Bundle.Accounts_BINNode_brandProperty_displayName(), Bundle.Accounts_BINNode_noDescription(),
 
 1493                 bin.
getBankName().ifPresent(bankName -> properties.put(
new NodeProperty<>(Bundle.Accounts_BINNode_bankProperty_displayName(),
 
 1494                         Bundle.Accounts_BINNode_bankProperty_displayName(), Bundle.Accounts_BINNode_noDescription(),
 
 1496                 bin.
getBankCity().ifPresent(bankCity -> properties.put(
new NodeProperty<>(Bundle.Accounts_BINNode_bankCityProperty_displayName(),
 
 1497                         Bundle.Accounts_BINNode_bankCityProperty_displayName(), Bundle.Accounts_BINNode_noDescription(),
 
 1499                 bin.
getCountry().ifPresent(country -> properties.put(
new NodeProperty<>(Bundle.Accounts_BINNode_bankCountryProperty_displayName(),
 
 1500                         Bundle.Accounts_BINNode_bankCountryProperty_displayName(), Bundle.Accounts_BINNode_noDescription(),
 
 1503                         Bundle.Accounts_BINNode_bankPhoneProperty_displayName(), Bundle.Accounts_BINNode_noDescription(),
 
 1505                 bin.
getBankURL().ifPresent(url -> properties.put(
new NodeProperty<>(Bundle.Accounts_BINNode_bankURLProperty_displayName(),
 
 1506                         Bundle.Accounts_BINNode_bankURLProperty_displayName(), Bundle.Accounts_BINNode_noDescription(),
 
 1513             this.setSheet(createSheet());
 
 1528             hash = 97 * hash + this.binEnd;
 
 1529             hash = 97 * hash + this.binStart;
 
 1541             if (getClass() != obj.getClass()) {
 
 1545             if (this.binEnd != other.
binEnd) {
 
 1548             if (this.binStart != other.
binStart) {
 
 1563             this.binRange = binRange;
 
 1564             binStart = binRange.getBINstart();
 
 1565             binEnd = binRange.getBINend();
 
 1570             this.binRange = null;
 
 1587         boolean hasDetails() {
 
 1588             return binRange != null;
 
 1642             super(artifact, 
"org/sleuthkit/autopsy/images/credit-card.png");   
 
 1643             this.artifact = artifact;
 
 1644             setName(Long.toString(
this.artifact.getArtifactID()));
 
 1646             reviewStatusBus.register(
this);
 
 1651             List<Action> actionsList = 
new ArrayList<>();
 
 1652             actionsList.addAll(Arrays.asList(super.getActions(context)));
 
 1654             actionsList.add(approveActionInstance);
 
 1655             actionsList.add(rejectActionInstance);
 
 1657             return actionsList.toArray(
new Action[actionsList.size()]);
 
 1662             Sheet sheet = super.createSheet();
 
 1663             Sheet.Set properties = sheet.get(Sheet.PROPERTIES);
 
 1664             if (properties == null) {
 
 1665                 properties = Sheet.createPropertiesSet();
 
 1666                 sheet.put(properties);
 
 1668             properties.put(
new NodeProperty<>(Bundle.Accounts_FileWithCCNNode_statusProperty_displayName(),
 
 1669                     Bundle.Accounts_FileWithCCNNode_statusProperty_displayName(),
 
 1670                     Bundle.Accounts_FileWithCCNNode_noDescription(),
 
 1671                     artifact.getReviewStatus().getDisplayName()));
 
 1680             event.artifacts.stream().filter((art) -> (art.getArtifactID() == this.artifact.getArtifactID())).map((_item) -> {
 
 1682             }).forEachOrdered((_item) -> {
 
 1688             this.setSheet(createSheet());
 
 1696         @NbBundle.Messages(
"ToggleShowRejected.name=Show Rejected Results")
 
 1698             super(Bundle.ToggleShowRejected_name());
 
 1724             this.newStatus = newStatus;
 
 1733             List<String[]> selectedPaths = Utilities.actionsGlobalContext().lookupAll(Node.class).stream()
 
 1735                         String[] createPath;
 
 1741                         if (newStatus == BlackboardArtifact.ReviewStatus.REJECTED && showRejected == 
false) {
 
 1742                             List<Node> siblings = Arrays.asList(node.getParentNode().getChildren().getNodes());
 
 1743                             if (siblings.size() > 1) {
 
 1744                                 int indexOf = siblings.indexOf(node);
 
 1746                                 Node sibling = indexOf > 0
 
 1747                                         ? siblings.get(indexOf - 1)
 
 1748                                         : siblings.get(Integer.max(indexOf + 1, siblings.size() - 1));
 
 1749                                 createPath = NodeOp.createPath(sibling, null);
 
 1757                             createPath = NodeOp.createPath(node, null);
 
 1760                         return Arrays.copyOfRange(createPath, 1, createPath.length);
 
 1762                     .filter(Objects::nonNull)
 
 1763                     .collect(Collectors.toList());
 
 1766             final Collection<? extends BlackboardArtifact> artifacts = Utilities.actionsGlobalContext().lookupAll(BlackboardArtifact.class);
 
 1767             artifacts.forEach(artifact -> {
 
 1769                     artifact.setReviewStatus(newStatus);
 
 1770                 } 
catch (TskCoreException ex) {
 
 1771                     LOGGER.log(Level.SEVERE, 
"Error changing artifact review status.", ex); 
 
 1775             reviewStatusBus.post(
new ReviewStatusChangeEvent(artifacts, newStatus));
 
 1777             final DataResultTopComponent directoryListing = DirectoryTreeTopComponent.findInstance().getDirectoryListing();
 
 1778             final Node rootNode = directoryListing.getRootNode();
 
 1781             List<Node> toArray = 
new ArrayList<>();
 
 1782             selectedPaths.forEach(path -> {
 
 1784                     toArray.add(NodeOp.findPath(rootNode, path));
 
 1785                 } 
catch (NodeNotFoundException ex) { 
 
 1790             directoryListing.setSelectedNodes(toArray.toArray(
new Node[toArray.size()]));
 
 1796         @NbBundle.Messages({
"ApproveAccountsAction.name=Approve Accounts"})
 
 1798             super(Bundle.ApproveAccountsAction_name(), BlackboardArtifact.ReviewStatus.APPROVED);
 
 1804         @NbBundle.Messages({
"RejectAccountsAction.name=Reject Accounts"})
 
 1806             super(Bundle.RejectAccountsAction_name(), BlackboardArtifact.ReviewStatus.REJECTED);
 
 1812         Collection<? extends BlackboardArtifact> artifacts;
 
 1813         BlackboardArtifact.ReviewStatus newReviewStatus;
 
 1815         ReviewStatusChangeEvent(Collection<? extends BlackboardArtifact> artifacts, BlackboardArtifact.ReviewStatus newReviewStatus) {
 
 1816             this.artifacts = artifacts;
 
 1817             this.newReviewStatus = newReviewStatus;
 
 1828         if (type.equals(Account.Type.CREDIT_CARD)) {
 
 1829             return ICON_BASE_PATH + 
"credit-card.png";
 
 1830         } 
else if (type.equals(Account.Type.DEVICE)) {
 
 1831             return ICON_BASE_PATH + 
"image.png";
 
 1832         } 
else if (type.equals(Account.Type.EMAIL)) {
 
 1833             return ICON_BASE_PATH + 
"email.png";
 
 1834         } 
else if (type.equals(Account.Type.FACEBOOK)) {
 
 1835             return ICON_BASE_PATH + 
"facebook.png";
 
 1836         } 
else if (type.equals(Account.Type.INSTAGRAM)) {
 
 1837             return ICON_BASE_PATH + 
"instagram.png";
 
 1838         } 
else if (type.equals(Account.Type.MESSAGING_APP)) {
 
 1839             return ICON_BASE_PATH + 
"messaging.png";
 
 1840         } 
else if (type.equals(Account.Type.PHONE)) {
 
 1841             return ICON_BASE_PATH + 
"phone.png";
 
 1842         } 
else if (type.equals(Account.Type.TWITTER)) {
 
 1843             return ICON_BASE_PATH + 
"twitter.png";
 
 1844         } 
else if (type.equals(Account.Type.WEBSITE)) {
 
 1845             return ICON_BASE_PATH + 
"web-file.png";
 
 1846         } 
else if (type.equals(Account.Type.WHATSAPP)) {
 
 1847             return ICON_BASE_PATH + 
"WhatsApp.png";
 
 1850             throw new IllegalArgumentException(
"Unknown Account.Type: " + type.getTypeName());
 
CreditCardNumberFactory(BinResult bin)
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
T visit(DataSourcesNode in)
Node[] createNodesForKey(CreditCardViewMode key)
void removeIngestJobEventListener(final PropertyChangeListener listener)
Optional< String > getScheme()
final Set< BlackboardArtifact.ReviewStatus > statuses
Optional< String > getBrand()
final long datasourceObjId
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)
static Boolean getGroupItemsInTreeByDataSource()
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)
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)