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.lookup.Lookups;
 
   79 import org.
sleuthkit.datamodel.BlackboardArtifact.ARTIFACT_TYPE;
 
   93     private static final String 
ICON_BASE_PATH = 
"/org/sleuthkit/autopsy/images/"; 
 
   97     @NbBundle.Messages(
"AccountsRootNode.name=Accounts")
 
   98     final public static String 
NAME = Bundle.AccountsRootNode_name();
 
  131     public Accounts(SleuthkitCase skCase, 
long objId) {
 
  133         this.filteringDSObjId = objId;
 
  142         return visitor.
visit(
this);
 
  153         return showRejected ? 
" " : 
" AND blackboard_artifacts.review_status_id != " + BlackboardArtifact.ReviewStatus.REJECTED.getID() + 
" "; 
 
  163         if (filteringDSObjId > 0) {
 
  164             return "  AND blackboard_artifacts.data_source_obj_id = " + filteringDSObjId + 
" ";
 
  203         abstract protected boolean createKeys(List<X> list);
 
  218             super.removeNotify();
 
  233     @NbBundle.Messages({
"Accounts.RootNode.displayName=Accounts"})
 
  239             setDisplayName(Bundle.Accounts_RootNode_displayName());
 
  240             this.setIconBaseWithExtension(
"org/sleuthkit/autopsy/images/accounts.png");    
 
  250             return visitor.
visit(
this);
 
  255             return getClass().getName();
 
  263         private final Map<String, Long> 
counts = 
new HashMap<>();
 
  274         Long getCount(String accountType) {
 
  275             return counts.get(accountType);
 
  282         List<String> getTypes() {
 
  283             List<String> types = 
new ArrayList<>(counts.keySet());
 
  284             Collections.sort(types);
 
  292             String accountTypesInUseQuery
 
  293                     = 
"SELECT blackboard_attributes.value_text as account_type, COUNT(*) as count " 
  294                     + 
" FROM blackboard_artifacts "  
  295                     + 
"      JOIN blackboard_attributes ON blackboard_artifacts.artifact_id = blackboard_attributes.artifact_id "  
  296                     + 
" WHERE blackboard_artifacts.artifact_type_id = " + BlackboardArtifact.ARTIFACT_TYPE.TSK_ACCOUNT.getTypeID() 
 
  297                     + 
" AND blackboard_attributes.attribute_type_id = " + BlackboardAttribute.ATTRIBUTE_TYPE.TSK_ACCOUNT_TYPE.getTypeID() 
 
  299                     + 
" GROUP BY blackboard_attributes.value_text ";
 
  301             try (SleuthkitCase.CaseDbQuery executeQuery = skCase.executeQuery(accountTypesInUseQuery);
 
  302                     ResultSet resultSet = executeQuery.getResultSet()) {
 
  305                 while (resultSet.next()) {
 
  306                     String accountType = resultSet.getString(
"account_type");
 
  307                     Long count = resultSet.getLong(
"count");
 
  308                     counts.put(accountType, count);
 
  310             } 
catch (TskCoreException | SQLException ex) {
 
  311                 LOGGER.log(Level.SEVERE, 
"Error querying for account_types", ex);
 
  325         private final PropertyChangeListener 
pcl = 
new PropertyChangeListener() {
 
  327             public void propertyChange(PropertyChangeEvent evt) {
 
  328                 String eventType = evt.getPropertyName();
 
  345                         if (null != eventData
 
  347                             accountTypeResults.
update();
 
  348                             reviewStatusBus.post(eventData);
 
  369                     if (evt.getNewValue() == null) {
 
  391             list.addAll(accountTypeResults.getTypes());
 
  402             reviewStatusBus.register(node);
 
  403             return new Node[]{node};
 
  409             if (Account.Type.CREDIT_CARD.getTypeName().equals(acountTypeName)) {
 
  414                     Account.Type accountType = skCase.getCommunicationsManager().getAccountType(acountTypeName);
 
  416                 } 
catch (TskCoreException ex) {
 
  417                     LOGGER.log(Level.SEVERE, 
"Error getting display name for account type. ", ex);
 
  429             super.removeNotify();
 
  451         private final PropertyChangeListener 
pcl = 
new PropertyChangeListener() {
 
  453             public void propertyChange(PropertyChangeEvent evt) {
 
  454                 String eventType = evt.getPropertyName();
 
  471                         if (null != eventData
 
  473                             reviewStatusBus.post(eventData);
 
  495                     if (evt.getNewValue() == null) {
 
  516             super.removeNotify();
 
  522                     = 
"SELECT blackboard_artifacts.artifact_id "  
  523                     + 
" FROM blackboard_artifacts "  
  524                     + 
"      JOIN blackboard_attributes ON blackboard_artifacts.artifact_id = blackboard_attributes.artifact_id "  
  525                     + 
" WHERE blackboard_artifacts.artifact_type_id = " + BlackboardArtifact.ARTIFACT_TYPE.TSK_ACCOUNT.getTypeID() 
 
  526                     + 
"     AND blackboard_attributes.attribute_type_id = " + BlackboardAttribute.ATTRIBUTE_TYPE.TSK_ACCOUNT_TYPE.getTypeID() 
 
  527                     + 
"     AND blackboard_attributes.value_text = '" + accountType.getTypeName() + 
"'"  
  530             try (SleuthkitCase.CaseDbQuery results = skCase.executeQuery(query);
 
  531                     ResultSet rs = results.getResultSet();) {
 
  533                     list.add(rs.getLong(
"artifact_id")); 
 
  535             } 
catch (TskCoreException | SQLException ex) {
 
  536                 LOGGER.log(Level.SEVERE, 
"Error querying for account artifacts.", ex); 
 
  546             } 
catch (TskCoreException ex) {
 
  547                 LOGGER.log(Level.SEVERE, 
"Error get black board artifact with id " + t, ex);
 
  573             super(Children.create(
new DefaultAccountFactory(accountType), 
true), Lookups.singleton(accountType));
 
  576             this.setIconBaseWithExtension(iconPath != null && iconPath.charAt(0) == 
'/' ? iconPath.substring(1) : iconPath);   
 
  587             return visitor.
visit(
this);
 
  592             return getClass().getName();
 
  610             setName(String.format(
"%s (%d)", accountType.getDisplayName(), accountTypeResults.getCount(accountType.getTypeName())));
 
  624         private final PropertyChangeListener pcl = 
new PropertyChangeListener() {
 
  626             public void propertyChange(PropertyChangeEvent evt) {
 
  627                 String eventType = evt.getPropertyName();
 
  644                         if (null != eventData
 
  646                             reviewStatusBus.post(eventData);
 
  668                     if (evt.getNewValue() == null) {
 
  701             super.removeNotify();
 
  708         protected boolean createKeys(List<CreditCardViewMode> list) {
 
  737             super(Children.create(
new ViewModeFactory(), 
true), Lookups.singleton(Account.Type.CREDIT_CARD.getDisplayName()));
 
  738             setName(Account.Type.CREDIT_CARD.getDisplayName());
 
  739             this.setIconBaseWithExtension(
"org/sleuthkit/autopsy/images/credit-cards.png");   
 
  746             setName(String.format(
"%s (%d)", Account.Type.CREDIT_CARD.getDisplayName(), accountTypeResults.getCount(Account.Type.CREDIT_CARD.getTypeName())));
 
  766             return visitor.
visit(
this);
 
  771             return getClass().getName();
 
  777         private final PropertyChangeListener pcl = 
new PropertyChangeListener() {
 
  779             public void propertyChange(PropertyChangeEvent evt) {
 
  780                 String eventType = evt.getPropertyName();
 
  797                         if (null != eventData
 
  799                             reviewStatusBus.post(eventData);
 
  821                     if (evt.getNewValue() == null) {
 
  842             super.removeNotify();
 
  860                     = 
"SELECT blackboard_artifacts.obj_id,"  
  861                     + 
"      solr_attribute.value_text AS solr_document_id, "; 
 
  862             if (skCase.getDatabaseType().equals(DbType.POSTGRESQL)) {
 
  863                 query += 
"      string_agg(blackboard_artifacts.artifact_id::character varying, ',') AS artifact_IDs, "  
  864                         + 
"      string_agg(blackboard_artifacts.review_status_id::character varying, ',') AS review_status_ids, ";
 
  866                 query += 
"      GROUP_CONCAT(blackboard_artifacts.artifact_id) AS artifact_IDs, "  
  867                         + 
"      GROUP_CONCAT(blackboard_artifacts.review_status_id) AS review_status_ids, ";
 
  869             query += 
"      COUNT( blackboard_artifacts.artifact_id) AS hits  "  
  870                     + 
" FROM blackboard_artifacts "  
  871                     + 
" LEFT JOIN blackboard_attributes as solr_attribute ON blackboard_artifacts.artifact_id = solr_attribute.artifact_id "  
  872                     + 
"                                AND solr_attribute.attribute_type_id = " + BlackboardAttribute.ATTRIBUTE_TYPE.TSK_KEYWORD_SEARCH_DOCUMENT_ID.getTypeID() 
 
  873                     + 
" LEFT JOIN blackboard_attributes as account_type ON blackboard_artifacts.artifact_id = account_type.artifact_id "  
  874                     + 
"                                AND account_type.attribute_type_id = " + BlackboardAttribute.ATTRIBUTE_TYPE.TSK_ACCOUNT_TYPE.getTypeID() 
 
  875                     + 
"                                AND account_type.value_text = '" + Account.Type.CREDIT_CARD.getTypeName() + 
"'"  
  876                     + 
" WHERE blackboard_artifacts.artifact_type_id = " + BlackboardArtifact.ARTIFACT_TYPE.TSK_ACCOUNT.getTypeID() 
 
  879                     + 
" GROUP BY blackboard_artifacts.obj_id, solr_document_id "  
  880                     + 
" ORDER BY hits DESC ";  
 
  881             try (SleuthkitCase.CaseDbQuery results = skCase.executeQuery(query);
 
  882                     ResultSet resultSet = results.getResultSet();) {
 
  883                 while (resultSet.next()) {
 
  885                             resultSet.getLong(
"obj_id"), 
 
  886                             resultSet.getString(
"solr_document_id"), 
 
  887                             unGroupConcat(resultSet.getString(
"artifact_IDs"), Long::valueOf), 
 
  888                             resultSet.getLong(
"hits"), 
 
  889                             new HashSet<>(unGroupConcat(resultSet.getString(
"review_status_ids"), reviewStatusID -> BlackboardArtifact.ReviewStatus.withID(Integer.valueOf(reviewStatusID))))));  
 
  891             } 
catch (TskCoreException | SQLException ex) {
 
  892                 LOGGER.log(Level.SEVERE, 
"Error querying for files with ccn hits.", ex); 
 
  902                 List<Object> lookupContents = 
new ArrayList<>();
 
  904                     lookupContents.add(skCase.getBlackboardArtifact(artId));
 
  906                 AbstractFile abstractFileById = skCase.getAbstractFileById(key.
getObjID());
 
  907                 lookupContents.add(abstractFileById);
 
  908                 return new Node[]{
new FileWithCCNNode(key, abstractFileById, lookupContents.toArray())};
 
  909             } 
catch (TskCoreException ex) {
 
  910                 LOGGER.log(Level.SEVERE, 
"Error getting content for file with ccn hits.", ex); 
 
  929             this.setIconBaseWithExtension(
"org/sleuthkit/autopsy/images/file-icon.png");   
 
  930             reviewStatusBus.register(
this);
 
  934             "# {0} - number of children",
 
  935             "Accounts.ByFileNode.displayName=By File ({0})"})
 
  938                     = 
"SELECT count(*) FROM ( SELECT count(*) AS documents " 
  939                     + 
" FROM blackboard_artifacts "  
  940                     + 
" LEFT JOIN blackboard_attributes as solr_attribute ON blackboard_artifacts.artifact_id = solr_attribute.artifact_id "  
  941                     + 
"                                AND solr_attribute.attribute_type_id = " + BlackboardAttribute.ATTRIBUTE_TYPE.TSK_KEYWORD_SEARCH_DOCUMENT_ID.getTypeID() 
 
  942                     + 
" LEFT JOIN blackboard_attributes as account_type ON blackboard_artifacts.artifact_id = account_type.artifact_id "  
  943                     + 
"                                AND account_type.attribute_type_id = " + BlackboardAttribute.ATTRIBUTE_TYPE.TSK_ACCOUNT_TYPE.getTypeID() 
 
  944                     + 
"                                AND account_type.value_text = '" + Account.Type.CREDIT_CARD.getTypeName() + 
"'"  
  945                     + 
" WHERE blackboard_artifacts.artifact_type_id = " + BlackboardArtifact.ARTIFACT_TYPE.TSK_ACCOUNT.getTypeID() 
 
  948                     + 
" GROUP BY blackboard_artifacts.obj_id, solr_attribute.value_text ) AS foo";
 
  949             try (SleuthkitCase.CaseDbQuery results = skCase.executeQuery(query);
 
  950                     ResultSet resultSet = results.getResultSet();) {
 
  951                 while (resultSet.next()) {
 
  952                     if (skCase.getDatabaseType().equals(DbType.POSTGRESQL)) {
 
  953                         setDisplayName(Bundle.Accounts_ByFileNode_displayName(resultSet.getLong(
"count")));
 
  955                         setDisplayName(Bundle.Accounts_ByFileNode_displayName(resultSet.getLong(
"count(*)")));
 
  958             } 
catch (TskCoreException | SQLException ex) {
 
  959                 LOGGER.log(Level.SEVERE, 
"Error querying for files with ccn hits.", ex); 
 
  971             return visitor.
visit(
this);
 
  976             return getClass().getName();
 
  992         private final PropertyChangeListener pcl = 
new PropertyChangeListener() {
 
  994             public void propertyChange(PropertyChangeEvent evt) {
 
  995                 String eventType = evt.getPropertyName();
 
 1012                         if (null != eventData
 
 1014                             reviewStatusBus.post(eventData);
 
 1035                         && (evt.getNewValue() == null)) {
 
 1056             super.removeNotify();
 
 1074             RangeMap<Integer, BinResult> binRanges = TreeRangeMap.create();
 
 1077                     = 
"SELECT SUBSTR(blackboard_attributes.value_text,1,8) AS BIN, "  
 1078                     + 
"     COUNT(blackboard_artifacts.artifact_id) AS count "  
 1079                     + 
" FROM blackboard_artifacts "  
 1080                     + 
"      JOIN blackboard_attributes ON blackboard_artifacts.artifact_id = blackboard_attributes.artifact_id"  
 1081                     + 
" WHERE blackboard_artifacts.artifact_type_id = " + BlackboardArtifact.ARTIFACT_TYPE.TSK_ACCOUNT.getTypeID() 
 
 1082                     + 
"     AND blackboard_attributes.attribute_type_id = " + BlackboardAttribute.ATTRIBUTE_TYPE.TSK_CARD_NUMBER.getTypeID() 
 
 1087             try (SleuthkitCase.CaseDbQuery results = skCase.executeQuery(query);
 
 1088                     ResultSet resultSet = results.getResultSet();) {
 
 1090                 while (resultSet.next()) {
 
 1091                     final Integer bin = Integer.valueOf(resultSet.getString(
"BIN"));
 
 1092                     long count = resultSet.getLong(
"count");
 
 1095                     BinResult previousResult = binRanges.get(bin);
 
 1097                     if (previousResult != null) {
 
 1098                         binRanges.remove(Range.closed(previousResult.getBINStart(), previousResult.getBINEnd()));
 
 1099                         count += previousResult.getCount();
 
 1102                     if (binRange == null) {
 
 1103                         binRanges.put(Range.closed(bin, bin), 
new BinResult(count, bin, bin));
 
 1108                 binRanges.asMapOfRanges().values().forEach(list::add);
 
 1109             } 
catch (TskCoreException | SQLException ex) {
 
 1110                 LOGGER.log(Level.SEVERE, 
"Error querying for BINs.", ex); 
 
 1118             return new Node[]{
new BINNode(key)};
 
 1131         @NbBundle.Messages(
"Accounts.ByBINNode.name=By BIN")
 
 1133             super(Children.create(
new BINFactory(), 
true), Lookups.singleton(Bundle.Accounts_ByBINNode_name()));
 
 1134             setName(Bundle.Accounts_ByBINNode_name());  
 
 1135             updateDisplayName();
 
 1136             this.setIconBaseWithExtension(
"org/sleuthkit/autopsy/images/bank.png");   
 
 1137             reviewStatusBus.register(
this);
 
 1140         @NbBundle.Messages({
 
 1141             "# {0} - number of children",
 
 1142             "Accounts.ByBINNode.displayName=By BIN ({0})"})
 
 1145                     = 
"SELECT count(distinct SUBSTR(blackboard_attributes.value_text,1,8)) AS BINs "  
 1146                     + 
" FROM blackboard_artifacts "  
 1147                     + 
"      JOIN blackboard_attributes ON blackboard_artifacts.artifact_id = blackboard_attributes.artifact_id"  
 1148                     + 
" WHERE blackboard_artifacts.artifact_type_id = " + BlackboardArtifact.ARTIFACT_TYPE.TSK_ACCOUNT.getTypeID() 
 
 1149                     + 
"     AND blackboard_attributes.attribute_type_id = " + BlackboardAttribute.ATTRIBUTE_TYPE.TSK_CARD_NUMBER.getTypeID() 
 
 1152             try (SleuthkitCase.CaseDbQuery results = skCase.executeQuery(query);
 
 1153                     ResultSet resultSet = results.getResultSet();) {
 
 1154                 while (resultSet.next()) {
 
 1155                     setDisplayName(Bundle.Accounts_ByBINNode_displayName(resultSet.getLong(
"BINs")));
 
 1157             } 
catch (TskCoreException | SQLException ex) {
 
 1158                 LOGGER.log(Level.SEVERE, 
"Error querying for BINs.", ex); 
 
 1169             return visitor.
visit(
this);
 
 1174             return getClass().getName();
 
 1179             updateDisplayName();
 
 1184             updateDisplayName();
 
 1198             hash = 79 * hash + (int) (this.objID ^ (this.objID >>> 32));
 
 1199             hash = 79 * hash + Objects.hashCode(this.keywordSearchDocID);
 
 1200             hash = 79 * hash + Objects.hashCode(this.artifactIDs);
 
 1201             hash = 79 * hash + (int) (this.hits ^ (this.hits >>> 32));
 
 1202             hash = 79 * hash + Objects.hashCode(this.statuses);
 
 1214             if (getClass() != obj.getClass()) {
 
 1218             if (this.objID != other.
objID) {
 
 1221             if (this.hits != other.
hits) {
 
 1227             if (!Objects.equals(
this.artifactIDs, other.
artifactIDs)) {
 
 1230             if (!Objects.equals(
this.statuses, other.
statuses)) {
 
 1240         private final Set<BlackboardArtifact.ReviewStatus> 
statuses;
 
 1242         private FileWithCCN(
long objID, String solrDocID, List<Long> artifactIDs, 
long hits, Set<BlackboardArtifact.ReviewStatus> statuses) {
 
 1244             this.keywordSearchDocID = solrDocID;
 
 1245             this.artifactIDs = artifactIDs;
 
 1247             this.statuses = statuses;
 
 1266             return keywordSearchDocID;
 
 1275             return Collections.unmodifiableList(artifactIDs);
 
 1293             return Collections.unmodifiableSet(statuses);
 
 1313     static <X> List<X> unGroupConcat(String groupConcat, Function<String, X> mapper) {
 
 1314         return StringUtils.isBlank(groupConcat) ? Collections.emptyList()
 
 1315                 : Stream.of(groupConcat.split(
",")) 
 
 1317                         .collect(Collectors.toList());
 
 1337         @NbBundle.Messages({
 
 1338             "# {0} - raw file name",
 
 1339             "# {1} - solr chunk id",
 
 1340             "Accounts.FileWithCCNNode.unallocatedSpaceFile.displayName={0}_chunk_{1}"})
 
 1342             super(Children.LEAF, Lookups.fixed(lookupContents));
 
 1346                     : Bundle.Accounts_FileWithCCNNode_unallocatedSpaceFile_displayName(content.getName(), StringUtils.substringAfter(key.
getkeywordSearchDocID(), 
"_")); 
 
 1347             setName(fileName + key.
getObjID());
 
 1348             setDisplayName(fileName);
 
 1358             return visitor.
visit(
this);
 
 1363             return getClass().getName();
 
 1367         @NbBundle.Messages({
 
 1368             "Accounts.FileWithCCNNode.nameProperty.displayName=File",
 
 1369             "Accounts.FileWithCCNNode.accountsProperty.displayName=Accounts",
 
 1370             "Accounts.FileWithCCNNode.statusProperty.displayName=Status",
 
 1371             "Accounts.FileWithCCNNode.noDescription=no description"})
 
 1373             Sheet sheet = super.createSheet();
 
 1374             Sheet.Set propSet = sheet.get(Sheet.PROPERTIES);
 
 1375             if (propSet == null) {
 
 1376                 propSet = Sheet.createPropertiesSet();
 
 1380             propSet.put(
new NodeProperty<>(Bundle.Accounts_FileWithCCNNode_nameProperty_displayName(),
 
 1381                     Bundle.Accounts_FileWithCCNNode_nameProperty_displayName(),
 
 1382                     Bundle.Accounts_FileWithCCNNode_noDescription(),
 
 1384             propSet.put(
new NodeProperty<>(Bundle.Accounts_FileWithCCNNode_accountsProperty_displayName(),
 
 1385                     Bundle.Accounts_FileWithCCNNode_accountsProperty_displayName(),
 
 1386                     Bundle.Accounts_FileWithCCNNode_noDescription(),
 
 1388             propSet.put(
new NodeProperty<>(Bundle.Accounts_FileWithCCNNode_statusProperty_displayName(),
 
 1389                     Bundle.Accounts_FileWithCCNNode_statusProperty_displayName(),
 
 1390                     Bundle.Accounts_FileWithCCNNode_noDescription(),
 
 1392                             .map(BlackboardArtifact.ReviewStatus::getDisplayName)
 
 1393                             .collect(Collectors.joining(
", ")))); 
 
 1400             Action[] actions = super.getActions(context);
 
 1401             ArrayList<Action> arrayList = 
new ArrayList<>();
 
 1402             arrayList.addAll(Arrays.asList(actions));
 
 1405             } 
catch (TskCoreException ex) {
 
 1406                 LOGGER.log(Level.SEVERE, 
"Error gettung content by id", ex);
 
 1409             arrayList.add(approveActionInstance);
 
 1410             arrayList.add(rejectActionInstance);
 
 1412             return arrayList.toArray(
new Action[arrayList.size()]);
 
 1440                     = 
"SELECT blackboard_artifacts.artifact_id "  
 1441                     + 
" FROM blackboard_artifacts "  
 1442                     + 
"      JOIN blackboard_attributes ON blackboard_artifacts.artifact_id = blackboard_attributes.artifact_id "  
 1443                     + 
" WHERE blackboard_artifacts.artifact_type_id = " + BlackboardArtifact.ARTIFACT_TYPE.TSK_ACCOUNT.getTypeID() 
 
 1444                     + 
"     AND blackboard_attributes.attribute_type_id = " + BlackboardAttribute.ATTRIBUTE_TYPE.TSK_CARD_NUMBER.getTypeID() 
 
 1445                     + 
"     AND blackboard_attributes.value_text >= '" + bin.getBINStart() + 
"' AND  blackboard_attributes.value_text < '" + (bin.getBINEnd() + 1) + 
"'"  
 1448                     + 
" ORDER BY blackboard_attributes.value_text"; 
 
 1449             try (SleuthkitCase.CaseDbQuery results = skCase.executeQuery(query);
 
 1450                     ResultSet rs = results.getResultSet();) {
 
 1452                     list.add(rs.getLong(
"artifact_id")); 
 
 1454             } 
catch (TskCoreException | SQLException ex) {
 
 1455                 LOGGER.log(Level.SEVERE, 
"Error querying for account artifacts.", ex); 
 
 1463             if (skCase == null) {
 
 1468                 BlackboardArtifact art = skCase.getBlackboardArtifact(artifactID);
 
 1470             } 
catch (TskCoreException ex) {
 
 1471                 LOGGER.log(Level.SEVERE, 
"Error creating BlackboardArtifactNode for artifact with ID " + artifactID, ex);   
 
 1478         if (bin.getBINStart() == bin.getBINEnd()) {
 
 1479             return Integer.toString(bin.getBINStart());
 
 1481             return bin.getBINStart() + 
"-" + StringUtils.difference(bin.getBINStart() + 
"", bin.getBINEnd() + 
"");
 
 1496             updateDisplayName();
 
 1497             this.setIconBaseWithExtension(
"org/sleuthkit/autopsy/images/bank.png");   
 
 1498             reviewStatusBus.register(
this);
 
 1503             updateDisplayName();
 
 1509             updateDisplayName();
 
 1514                     = 
"SELECT count(blackboard_artifacts.artifact_id ) AS count"  
 1515                     + 
" FROM blackboard_artifacts "  
 1516                     + 
"      JOIN blackboard_attributes ON blackboard_artifacts.artifact_id = blackboard_attributes.artifact_id "  
 1517                     + 
" WHERE blackboard_artifacts.artifact_type_id = " + BlackboardArtifact.ARTIFACT_TYPE.TSK_ACCOUNT.getTypeID() 
 
 1518                     + 
"     AND blackboard_attributes.attribute_type_id = " + BlackboardAttribute.ATTRIBUTE_TYPE.TSK_CARD_NUMBER.getTypeID() 
 
 1519                     + 
"     AND blackboard_attributes.value_text >= '" + bin.getBINStart() + 
"' AND  blackboard_attributes.value_text < '" + (bin.getBINEnd() + 1) + 
"'"  
 1522             try (SleuthkitCase.CaseDbQuery results = skCase.executeQuery(query);
 
 1523                     ResultSet resultSet = results.getResultSet();) {
 
 1524                 while (resultSet.next()) {
 
 1525                     setDisplayName(
getBinRangeString(bin) + 
" (" + resultSet.getLong(
"count") + 
")"); 
 
 1527             } 
catch (TskCoreException | SQLException ex) {
 
 1528                 LOGGER.log(Level.SEVERE, 
"Error querying for account artifacts.", ex); 
 
 1541             return visitor.
visit(
this);
 
 1546             return getClass().getName();
 
 1550             Sheet.Set sheetSet = sheet.get(Sheet.PROPERTIES);
 
 1551             if (sheetSet == null) {
 
 1552                 sheetSet = Sheet.createPropertiesSet();
 
 1553                 sheet.put(sheetSet);
 
 1559         @NbBundle.Messages({
 
 1560             "Accounts.BINNode.binProperty.displayName=Bank Identifier Number",
 
 1561             "Accounts.BINNode.accountsProperty.displayName=Accounts",
 
 1562             "Accounts.BINNode.cardTypeProperty.displayName=Payment Card Type",
 
 1563             "Accounts.BINNode.schemeProperty.displayName=Credit Card Scheme",
 
 1564             "Accounts.BINNode.brandProperty.displayName=Brand",
 
 1565             "Accounts.BINNode.bankProperty.displayName=Bank",
 
 1566             "Accounts.BINNode.bankCityProperty.displayName=Bank City",
 
 1567             "Accounts.BINNode.bankCountryProperty.displayName=Bank Country",
 
 1568             "Accounts.BINNode.bankPhoneProperty.displayName=Bank Phone #",
 
 1569             "Accounts.BINNode.bankURLProperty.displayName=Bank URL",
 
 1570             "Accounts.BINNode.noDescription=no description"})
 
 1572             Sheet sheet = super.createSheet();
 
 1573             Sheet.Set properties = getPropertySet(sheet);
 
 1575             properties.put(
new NodeProperty<>(Bundle.Accounts_BINNode_binProperty_displayName(),
 
 1576                     Bundle.Accounts_BINNode_binProperty_displayName(),
 
 1577                     Bundle.Accounts_BINNode_noDescription(),
 
 1579             properties.put(
new NodeProperty<>(Bundle.Accounts_BINNode_accountsProperty_displayName(),
 
 1580                     Bundle.Accounts_BINNode_accountsProperty_displayName(), Bundle.Accounts_BINNode_noDescription(),
 
 1584             if (bin.hasDetails()) {
 
 1585                 bin.
getCardType().ifPresent(cardType -> properties.put(
new NodeProperty<>(Bundle.Accounts_BINNode_cardTypeProperty_displayName(),
 
 1586                         Bundle.Accounts_BINNode_cardTypeProperty_displayName(), Bundle.Accounts_BINNode_noDescription(),
 
 1588                 bin.
getScheme().ifPresent(scheme -> properties.put(
new NodeProperty<>(Bundle.Accounts_BINNode_schemeProperty_displayName(),
 
 1589                         Bundle.Accounts_BINNode_schemeProperty_displayName(), Bundle.Accounts_BINNode_noDescription(),
 
 1591                 bin.
getBrand().ifPresent(brand -> properties.put(
new NodeProperty<>(Bundle.Accounts_BINNode_brandProperty_displayName(),
 
 1592                         Bundle.Accounts_BINNode_brandProperty_displayName(), Bundle.Accounts_BINNode_noDescription(),
 
 1594                 bin.
getBankName().ifPresent(bankName -> properties.put(
new NodeProperty<>(Bundle.Accounts_BINNode_bankProperty_displayName(),
 
 1595                         Bundle.Accounts_BINNode_bankProperty_displayName(), Bundle.Accounts_BINNode_noDescription(),
 
 1597                 bin.
getBankCity().ifPresent(bankCity -> properties.put(
new NodeProperty<>(Bundle.Accounts_BINNode_bankCityProperty_displayName(),
 
 1598                         Bundle.Accounts_BINNode_bankCityProperty_displayName(), Bundle.Accounts_BINNode_noDescription(),
 
 1600                 bin.
getCountry().ifPresent(country -> properties.put(
new NodeProperty<>(Bundle.Accounts_BINNode_bankCountryProperty_displayName(),
 
 1601                         Bundle.Accounts_BINNode_bankCountryProperty_displayName(), Bundle.Accounts_BINNode_noDescription(),
 
 1604                         Bundle.Accounts_BINNode_bankPhoneProperty_displayName(), Bundle.Accounts_BINNode_noDescription(),
 
 1606                 bin.
getBankURL().ifPresent(url -> properties.put(
new NodeProperty<>(Bundle.Accounts_BINNode_bankURLProperty_displayName(),
 
 1607                         Bundle.Accounts_BINNode_bankURLProperty_displayName(), Bundle.Accounts_BINNode_noDescription(),
 
 1614             this.setSheet(createSheet());
 
 1629             hash = 97 * hash + this.binEnd;
 
 1630             hash = 97 * hash + this.binStart;
 
 1642             if (getClass() != obj.getClass()) {
 
 1646             if (this.binEnd != other.
binEnd) {
 
 1649             if (this.binStart != other.
binStart) {
 
 1666             this.binRange = binRange;
 
 1667             binStart = binRange.getBINstart();
 
 1668             binEnd = binRange.getBINend();
 
 1673             this.binRange = null;
 
 1690         boolean hasDetails() {
 
 1691             return binRange != null;
 
 1745             super(artifact, 
"org/sleuthkit/autopsy/images/credit-card.png");   
 
 1746             this.artifact = artifact;
 
 1747             setName(Long.toString(
this.artifact.getArtifactID()));
 
 1749             reviewStatusBus.register(
this);
 
 1754             List<Action> actionsList = 
new ArrayList<>();
 
 1755             actionsList.addAll(Arrays.asList(super.getActions(context)));
 
 1757             actionsList.add(approveActionInstance);
 
 1758             actionsList.add(rejectActionInstance);
 
 1760             return actionsList.toArray(
new Action[actionsList.size()]);
 
 1765             Sheet sheet = super.createSheet();
 
 1766             Sheet.Set properties = sheet.get(Sheet.PROPERTIES);
 
 1767             if (properties == null) {
 
 1768                 properties = Sheet.createPropertiesSet();
 
 1769                 sheet.put(properties);
 
 1771             properties.put(
new NodeProperty<>(Bundle.Accounts_FileWithCCNNode_statusProperty_displayName(),
 
 1772                     Bundle.Accounts_FileWithCCNNode_statusProperty_displayName(),
 
 1773                     Bundle.Accounts_FileWithCCNNode_noDescription(),
 
 1774                     artifact.getReviewStatus().getDisplayName()));
 
 1783             event.artifacts.stream().filter((art) -> (art.getArtifactID() == this.artifact.getArtifactID())).map((_item) -> {
 
 1785             }).forEachOrdered((_item) -> {
 
 1791             this.setSheet(createSheet());
 
 1799         @NbBundle.Messages(
"ToggleShowRejected.name=Show Rejected Results")
 
 1801             super(Bundle.ToggleShowRejected_name());
 
 1827             this.newStatus = newStatus;
 
 1838             List<String[]> selectedPaths = Utilities.actionsGlobalContext().lookupAll(Node.class).stream()
 
 1840                         String[] createPath;
 
 1846                         if (newStatus == BlackboardArtifact.ReviewStatus.REJECTED && showRejected == 
false) {
 
 1847                             List<Node> siblings = Arrays.asList(node.getParentNode().getChildren().getNodes());
 
 1848                             if (siblings.size() > 1) {
 
 1849                                 int indexOf = siblings.indexOf(node);
 
 1851                                 Node sibling = indexOf > 0
 
 1852                                         ? siblings.get(indexOf - 1)
 
 1853                                         : siblings.get(Integer.max(indexOf + 1, siblings.size() - 1));
 
 1854                                 createPath = NodeOp.createPath(sibling, null);
 
 1864                             createPath = NodeOp.createPath(node, null);
 
 1867                         return Arrays.copyOfRange(createPath, 1, createPath.length);
 
 1869                     .filter(Objects::nonNull)
 
 1870                     .collect(Collectors.toList());
 
 1873             final Collection<? extends BlackboardArtifact> artifacts = Utilities.actionsGlobalContext().lookupAll(BlackboardArtifact.class);
 
 1874             artifacts.forEach(artifact -> {
 
 1876                     artifact.setReviewStatus(newStatus);
 
 1877                 } 
catch (TskCoreException ex) {
 
 1878                     LOGGER.log(Level.SEVERE, 
"Error changing artifact review status.", ex); 
 
 1882             reviewStatusBus.post(
new ReviewStatusChangeEvent(artifacts, newStatus));
 
 1884             final DataResultTopComponent directoryListing = DirectoryTreeTopComponent.findInstance().getDirectoryListing();
 
 1885             final Node rootNode = directoryListing.getRootNode();
 
 1888             List<Node> toArray = 
new ArrayList<>();
 
 1889             selectedPaths.forEach(path -> {
 
 1891                     toArray.add(NodeOp.findPath(rootNode, path));
 
 1892                 } 
catch (NodeNotFoundException ex) { 
 
 1897             directoryListing.setSelectedNodes(toArray.toArray(
new Node[toArray.size()]));
 
 1903         @NbBundle.Messages({
"ApproveAccountsAction.name=Approve Accounts"})
 
 1905             super(Bundle.ApproveAccountsAction_name(), BlackboardArtifact.ReviewStatus.APPROVED);
 
 1911         @NbBundle.Messages({
"RejectAccountsAction.name=Reject Accounts"})
 
 1913             super(Bundle.RejectAccountsAction_name(), BlackboardArtifact.ReviewStatus.REJECTED);
 
 1919         Collection<? extends BlackboardArtifact> artifacts;
 
 1920         BlackboardArtifact.ReviewStatus newReviewStatus;
 
 1922         ReviewStatusChangeEvent(Collection<? extends BlackboardArtifact> artifacts, BlackboardArtifact.ReviewStatus newReviewStatus) {
 
 1923             this.artifacts = artifacts;
 
 1924             this.newReviewStatus = newReviewStatus;
 
 1935         if (type.equals(Account.Type.CREDIT_CARD)) {
 
 1936             return ICON_BASE_PATH + 
"credit-card.png";
 
 1937         } 
else if (type.equals(Account.Type.DEVICE)) {
 
 1938             return ICON_BASE_PATH + 
"image.png";
 
 1939         } 
else if (type.equals(Account.Type.EMAIL)) {
 
 1940             return ICON_BASE_PATH + 
"email.png";
 
 1941         } 
else if (type.equals(Account.Type.FACEBOOK)) {
 
 1942             return ICON_BASE_PATH + 
"facebook.png";
 
 1943         } 
else if (type.equals(Account.Type.INSTAGRAM)) {
 
 1944             return ICON_BASE_PATH + 
"instagram.png";
 
 1945         } 
else if (type.equals(Account.Type.MESSAGING_APP)) {
 
 1946             return ICON_BASE_PATH + 
"messaging.png";
 
 1947         } 
else if (type.equals(Account.Type.PHONE)) {
 
 1948             return ICON_BASE_PATH + 
"phone.png";
 
 1949         } 
else if (type.equals(Account.Type.TWITTER)) {
 
 1950             return ICON_BASE_PATH + 
"twitter.png";
 
 1951         } 
else if (type.equals(Account.Type.WEBSITE)) {
 
 1952             return ICON_BASE_PATH + 
"web-file.png";
 
 1953         } 
else if (type.equals(Account.Type.WHATSAPP)) {
 
 1954             return ICON_BASE_PATH + 
"WhatsApp.png";
 
 1957             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
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)
final Account.Type accountType
Optional< String > getBankURL()
boolean createKeys(List< Long > list)
final Map< String, Long > counts
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 AccountTypeResults accountTypeResults
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)