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.HashSet;
 
   36 import java.util.List;
 
   37 import java.util.Objects;
 
   38 import java.util.Optional;
 
   40 import java.util.function.Function;
 
   41 import java.util.logging.Level;
 
   42 import java.util.logging.Logger;
 
   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.Children;
 
   51 import org.openide.nodes.Node;
 
   52 import org.openide.nodes.NodeNotFoundException;
 
   53 import org.openide.nodes.NodeOp;
 
   54 import org.openide.nodes.Sheet;
 
   55 import org.openide.util.NbBundle;
 
   56 import org.openide.util.Utilities;
 
   57 import org.openide.util.lookup.Lookups;
 
   74 import org.
sleuthkit.datamodel.BlackboardArtifact.ARTIFACT_TYPE;
 
   87     private static final Logger 
LOGGER = Logger.getLogger(
Accounts.class.getName());
 
   89     @NbBundle.Messages(
"AccountsRootNode.name=Accounts")
 
   90     final public static String 
NAME = Bundle.AccountsRootNode_name();
 
  117         return v.
visit(
this);
 
  128         return showRejected ? 
" " : 
" AND blackboard_artifacts.review_status_id != " + BlackboardArtifact.ReviewStatus.REJECTED.getID() + 
" "; 
 
  162         abstract protected Collection<X> 
createKeys();
 
  184             super.removeNotify();
 
  199     @NbBundle.Messages({
"Accounts.RootNode.displayName=Accounts"})
 
  211             private final PropertyChangeListener pcl = 
new PropertyChangeListener() {
 
  213                 public void propertyChange(PropertyChangeEvent evt) {
 
  214                     String eventType = evt.getPropertyName();
 
  232                             if (null != eventData
 
  234                                 reviewStatusBus.post(eventData);
 
  236                         } 
catch (IllegalStateException notUsed) {
 
  250                         } 
catch (IllegalStateException notUsed) {
 
  255                         if (evt.getNewValue() == null) {
 
  277                 List<String> list = 
new ArrayList<>();
 
  278                 try (SleuthkitCase.CaseDbQuery executeQuery = skCase.executeQuery(
 
  279                         "SELECT DISTINCT blackboard_attributes.value_text as account_type " 
  280                         + 
" FROM blackboard_attributes " 
  281                         + 
" WHERE blackboard_attributes.attribute_type_id = " + BlackboardAttribute.ATTRIBUTE_TYPE.TSK_ACCOUNT_TYPE.getTypeID());
 
  282                         ResultSet resultSet = executeQuery.getResultSet()) {
 
  283                     while (resultSet.next()) {
 
  284                         String accountType = resultSet.getString(
"account_type");
 
  285                         list.add(accountType);
 
  287                 } 
catch (TskCoreException | SQLException ex) {
 
  288                     LOGGER.log(Level.SEVERE, 
"Error querying for account_types", ex);
 
  296                     Account.Type accountType = Account.Type.valueOf(key);
 
  297                     switch (accountType) {
 
  303                 } 
catch (IllegalArgumentException ex) {
 
  304                     LOGGER.log(Level.WARNING, 
"Unknown account type: {0}", key);
 
  315                 super.removeNotify();
 
  330             super(Children.LEAF, Lookups.singleton(
Accounts.this));
 
  331             setChildren(Children.createLazy(AccountTypeFactory::new));
 
  333             setDisplayName(Bundle.Accounts_RootNode_displayName());
 
  334             this.setIconBaseWithExtension(
"org/sleuthkit/autopsy/images/accounts.png");    
 
  344             return v.
visit(
this);
 
  349             return getClass().getName();
 
  368                 List<Long> list = 
new ArrayList<>();
 
  370                         = 
"SELECT blackboard_artifacts.artifact_id "  
  371                         + 
" FROM blackboard_artifacts "  
  372                         + 
"      JOIN blackboard_attributes ON blackboard_artifacts.artifact_id = blackboard_attributes.artifact_id "  
  373                         + 
" WHERE blackboard_artifacts.artifact_type_id = " + BlackboardArtifact.ARTIFACT_TYPE.TSK_ACCOUNT.getTypeID() 
 
  374                         + 
"     AND blackboard_attributes.attribute_type_id = " + BlackboardAttribute.ATTRIBUTE_TYPE.TSK_ACCOUNT_TYPE.getTypeID() 
 
  375                         + 
"     AND blackboard_attributes.value_text = '" + accountTypeName + 
"'"  
  377                 try (SleuthkitCase.CaseDbQuery results = skCase.executeQuery(query);
 
  378                         ResultSet rs = results.getResultSet();) {
 
  380                         list.add(rs.getLong(
"artifact_id")); 
 
  382                 } 
catch (TskCoreException | SQLException ex) {
 
  383                     LOGGER.log(Level.SEVERE, 
"Error querying for account artifacts.", ex); 
 
  392                 } 
catch (TskCoreException ex) {
 
  393                     LOGGER.log(Level.SEVERE, 
"Error get black board artifact with id " + t, ex);
 
  412             super(Children.LEAF);
 
  414             setChildren(Children.createLazy(DefaultAccountFactory::new));
 
  415             setName(accountTypeName);
 
  416             this.setIconBaseWithExtension(
"org/sleuthkit/autopsy/images/credit-cards.png");   
 
  426             return v.
visit(
this);
 
  431             return getClass().getName();
 
  485             super(Children.LEAF);
 
  487             setName(Account.Type.CREDIT_CARD.getDisplayName());
 
  488             this.setIconBaseWithExtension(
"org/sleuthkit/autopsy/images/credit-cards.png");   
 
  498             return v.
visit(
this);
 
  503             return getClass().getName();
 
  532                 List<FileWithCCN> list = 
new ArrayList<>();
 
  534                         = 
"SELECT blackboard_artifacts.obj_id,"  
  535                         + 
"      solr_attribute.value_text AS solr_document_id, "; 
 
  536                 if(skCase.getDatabaseType().equals(DbType.POSTGRESQL)){
 
  537                     query += 
"      string_agg(blackboard_artifacts.artifact_id::character varying, ',') AS artifact_IDs, "  
  538                            + 
"      string_agg(blackboard_artifacts.review_status_id::character varying, ',') AS review_status_ids, ";
 
  540                     query += 
"      GROUP_CONCAT(blackboard_artifacts.artifact_id) AS artifact_IDs, "  
  541                            + 
"      GROUP_CONCAT(blackboard_artifacts.review_status_id) AS review_status_ids, ";
 
  543                 query +=  
"      COUNT( blackboard_artifacts.artifact_id) AS hits  "  
  544                         + 
" FROM blackboard_artifacts "  
  545                         + 
" LEFT JOIN blackboard_attributes as solr_attribute ON blackboard_artifacts.artifact_id = solr_attribute.artifact_id "  
  546                         + 
"                                AND solr_attribute.attribute_type_id = " + BlackboardAttribute.ATTRIBUTE_TYPE.TSK_KEYWORD_SEARCH_DOCUMENT_ID.getTypeID() 
 
  547                         + 
" LEFT JOIN blackboard_attributes as account_type ON blackboard_artifacts.artifact_id = account_type.artifact_id "  
  548                         + 
"                                AND account_type.attribute_type_id = " + BlackboardAttribute.ATTRIBUTE_TYPE.TSK_ACCOUNT_TYPE.getTypeID() 
 
  549                         + 
"                                AND account_type.value_text = '" + Account.Type.CREDIT_CARD.name() + 
"'"  
  550                         + 
" WHERE blackboard_artifacts.artifact_type_id = " + BlackboardArtifact.ARTIFACT_TYPE.TSK_ACCOUNT.getTypeID() 
 
  552                         + 
" GROUP BY blackboard_artifacts.obj_id, solr_document_id "  
  553                         + 
" ORDER BY hits DESC ";  
 
  554                 try (SleuthkitCase.CaseDbQuery results = skCase.executeQuery(query);
 
  555                         ResultSet rs = results.getResultSet();) {
 
  558                                 rs.getLong(
"obj_id"), 
 
  559                                 rs.getString(
"solr_document_id"), 
 
  560                                 unGroupConcat(rs.getString(
"artifact_IDs"), Long::valueOf), 
 
  562                                 new HashSet<>(unGroupConcat(rs.getString(
"review_status_ids"), 
id -> BlackboardArtifact.ReviewStatus.withID(Integer.valueOf(
id))))));  
 
  564                 } 
catch (TskCoreException | SQLException ex) {
 
  565                     LOGGER.log(Level.SEVERE, 
"Error querying for files with ccn hits.", ex); 
 
  575                     List<Object> lookupContents = 
new ArrayList<>();
 
  577                         lookupContents.add(skCase.getBlackboardArtifact(artId));
 
  579                     AbstractFile abstractFileById = skCase.getAbstractFileById(key.
getObjID());
 
  580                     lookupContents.add(abstractFileById);
 
  581                     return new Node[]{
new FileWithCCNNode(key, abstractFileById, lookupContents.toArray())};
 
  582                 } 
catch (TskCoreException ex) {
 
  583                     LOGGER.log(Level.SEVERE, 
"Error getting content for file with ccn hits.", ex); 
 
  590             super(Children.LEAF);
 
  591             setChildren(Children.createLazy(FileWithCCNFactory::new));
 
  594             this.setIconBaseWithExtension(
"org/sleuthkit/autopsy/images/file-icon.png");   
 
  595             reviewStatusBus.register(
this);
 
  599             "# {0} - number of children",
 
  600             "Accounts.ByFileNode.displayName=By File ({0})"})
 
  603                     = 
"SELECT count(*) FROM ( SELECT count(*) AS documents " 
  604                     + 
" FROM blackboard_artifacts "  
  605                     + 
" LEFT JOIN blackboard_attributes as solr_attribute ON blackboard_artifacts.artifact_id = solr_attribute.artifact_id "  
  606                     + 
"                                AND solr_attribute.attribute_type_id = " + BlackboardAttribute.ATTRIBUTE_TYPE.TSK_KEYWORD_SEARCH_DOCUMENT_ID.getTypeID() 
 
  607                     + 
" LEFT JOIN blackboard_attributes as account_type ON blackboard_artifacts.artifact_id = account_type.artifact_id "  
  608                     + 
"                                AND account_type.attribute_type_id = " + BlackboardAttribute.ATTRIBUTE_TYPE.TSK_ACCOUNT_TYPE.getTypeID() 
 
  609                     + 
"                                AND account_type.value_text = '" + Account.Type.CREDIT_CARD.name() + 
"'"  
  610                     + 
" WHERE blackboard_artifacts.artifact_type_id = " + BlackboardArtifact.ARTIFACT_TYPE.TSK_ACCOUNT.getTypeID() 
 
  612                     + 
" GROUP BY blackboard_artifacts.obj_id, solr_attribute.value_text ) AS foo";
 
  613             try (SleuthkitCase.CaseDbQuery results = skCase.executeQuery(query);
 
  614                     ResultSet rs = results.getResultSet();) {
 
  616                     if(skCase.getDatabaseType().equals(DbType.POSTGRESQL)){
 
  617                         setDisplayName(Bundle.Accounts_ByFileNode_displayName(rs.getLong(
"count")));
 
  619                         setDisplayName(Bundle.Accounts_ByFileNode_displayName(rs.getLong(
"count(*)")));
 
  622             } 
catch (TskCoreException | SQLException ex) {
 
  623                 LOGGER.log(Level.SEVERE, 
"Error querying for files with ccn hits.", ex); 
 
  635             return v.
visit(
this);
 
  640             return getClass().getName();
 
  679                 List<BinResult> list = 
new ArrayList<>();
 
  681                 RangeMap<Integer, BinResult> binRanges = TreeRangeMap.create();
 
  684                         = 
"SELECT SUBSTR(blackboard_attributes.value_text,1,8) AS BIN, "  
  685                         + 
"     COUNT(blackboard_artifacts.artifact_id) AS count "  
  686                         + 
" FROM blackboard_artifacts "  
  687                         + 
"      JOIN blackboard_attributes ON blackboard_artifacts.artifact_id = blackboard_attributes.artifact_id"  
  688                         + 
" WHERE blackboard_artifacts.artifact_type_id = " + BlackboardArtifact.ARTIFACT_TYPE.TSK_ACCOUNT.getTypeID() 
 
  689                         + 
"     AND blackboard_attributes.attribute_type_id = " + BlackboardAttribute.ATTRIBUTE_TYPE.TSK_CARD_NUMBER.getTypeID() 
 
  693                 try (SleuthkitCase.CaseDbQuery results = skCase.executeQuery(query)) {
 
  694                     ResultSet resultSet = results.getResultSet();
 
  696                     while (resultSet.next()) {
 
  697                         final Integer bin = Integer.valueOf(resultSet.getString(
"BIN"));
 
  698                         long count = resultSet.getLong(
"count");
 
  701                         BinResult previousResult = binRanges.get(bin);
 
  703                         if (previousResult != null) {
 
  704                             binRanges.remove(Range.closed(previousResult.getBINStart(), previousResult.getBINEnd()));
 
  705                             count += previousResult.getCount();
 
  708                         if (binRange != null) {
 
  711                             binRanges.put(Range.closed(bin, bin), 
new BinResult(count, bin, bin));
 
  714                     binRanges.asMapOfRanges().values().forEach(list::add);
 
  715                 } 
catch (TskCoreException | SQLException ex) {
 
  716                     LOGGER.log(Level.SEVERE, 
"Error querying for BINs.", ex); 
 
  724                 return new Node[]{
new BINNode(key)};
 
  729             super(Children.LEAF);
 
  730             setChildren(Children.createLazy(BINFactory::new));
 
  733             this.setIconBaseWithExtension(
"org/sleuthkit/autopsy/images/bank.png");   
 
  734             reviewStatusBus.register(
this);
 
  738             "# {0} - number of children",
 
  739             "Accounts.ByBINNode.displayName=By BIN ({0})"})
 
  742                     = 
"SELECT count(distinct SUBSTR(blackboard_attributes.value_text,1,8)) AS BINs "  
  743                     + 
" FROM blackboard_artifacts "  
  744                     + 
"      JOIN blackboard_attributes ON blackboard_artifacts.artifact_id = blackboard_attributes.artifact_id"  
  745                     + 
" WHERE blackboard_artifacts.artifact_type_id = " + BlackboardArtifact.ARTIFACT_TYPE.TSK_ACCOUNT.getTypeID() 
 
  746                     + 
"     AND blackboard_attributes.attribute_type_id = " + BlackboardAttribute.ATTRIBUTE_TYPE.TSK_CARD_NUMBER.getTypeID() 
 
  748             try (SleuthkitCase.CaseDbQuery results = skCase.executeQuery(query)) {
 
  749                 ResultSet resultSet = results.getResultSet();
 
  750                 while (resultSet.next()) {
 
  751                     setDisplayName(Bundle.Accounts_ByBINNode_displayName(resultSet.getLong(
"BINs")));
 
  753             } 
catch (TskCoreException | SQLException ex) {
 
  754                 LOGGER.log(Level.SEVERE, 
"Error querying for BINs.", ex); 
 
  765             return v.
visit(
this);
 
  770             return getClass().getName();
 
  794             hash = 79 * hash + (int) (this.objID ^ (this.objID >>> 32));
 
  795             hash = 79 * hash + Objects.hashCode(this.keywordSearchDocID);
 
  796             hash = 79 * hash + Objects.hashCode(this.artifactIDs);
 
  797             hash = 79 * hash + (int) (this.hits ^ (this.hits >>> 32));
 
  798             hash = 79 * hash + Objects.hashCode(this.statuses);
 
  810             if (getClass() != obj.getClass()) {
 
  814             if (this.objID != other.
objID) {
 
  817             if (this.hits != other.
hits) {
 
  823             if (!Objects.equals(
this.artifactIDs, other.
artifactIDs)) {
 
  826             if (!Objects.equals(
this.statuses, other.
statuses)) {
 
  836         private final Set<BlackboardArtifact.ReviewStatus> 
statuses;
 
  838         private FileWithCCN(
long objID, String solrDocID, List<Long> artifactIDs, 
long hits, Set<BlackboardArtifact.ReviewStatus> statuses) {
 
  840             this.keywordSearchDocID = solrDocID;
 
  841             this.artifactIDs = artifactIDs;
 
  843             this.statuses = statuses;
 
  862             return keywordSearchDocID;
 
  909     static <X> List<X> unGroupConcat(String groupConcat, Function<String, X> mapper) {
 
  910         return StringUtils.isBlank(groupConcat) ? Collections.emptyList()
 
  911                 : Stream.of(groupConcat.split(
",")) 
 
  913                 .collect(Collectors.toList());
 
  934             "# {0} - raw file name",
 
  935             "# {1} - solr chunk id",
 
  936             "Accounts.FileWithCCNNode.unallocatedSpaceFile.displayName={0}_chunk_{1}"})
 
  938             super(Children.LEAF, Lookups.fixed(lookupContents));
 
  942                     : Bundle.Accounts_FileWithCCNNode_unallocatedSpaceFile_displayName(content.getName(), StringUtils.substringAfter(key.
getkeywordSearchDocID(), 
"_")); 
 
  944             setDisplayName(fileName);
 
  954             return v.
visit(
this);
 
  959             return getClass().getName();
 
  964             "Accounts.FileWithCCNNode.nameProperty.displayName=File",
 
  965             "Accounts.FileWithCCNNode.accountsProperty.displayName=Accounts",
 
  966             "Accounts.FileWithCCNNode.statusProperty.displayName=Status",
 
  967             "Accounts.FileWithCCNNode.noDescription=no description"})
 
  969             Sheet s = super.createSheet();
 
  970             Sheet.Set ss = s.get(Sheet.PROPERTIES);
 
  972                 ss = Sheet.createPropertiesSet();
 
  976             ss.put(
new NodeProperty<>(Bundle.Accounts_FileWithCCNNode_nameProperty_displayName(),
 
  977                     Bundle.Accounts_FileWithCCNNode_nameProperty_displayName(),
 
  978                     Bundle.Accounts_FileWithCCNNode_noDescription(),
 
  980             ss.put(
new NodeProperty<>(Bundle.Accounts_FileWithCCNNode_accountsProperty_displayName(),
 
  981                     Bundle.Accounts_FileWithCCNNode_accountsProperty_displayName(),
 
  982                     Bundle.Accounts_FileWithCCNNode_noDescription(),
 
  984             ss.put(
new NodeProperty<>(Bundle.Accounts_FileWithCCNNode_statusProperty_displayName(),
 
  985                     Bundle.Accounts_FileWithCCNNode_statusProperty_displayName(),
 
  986                     Bundle.Accounts_FileWithCCNNode_noDescription(),
 
  988                     .map(BlackboardArtifact.ReviewStatus::getDisplayName)
 
  989                     .collect(Collectors.joining(
", ")))); 
 
  996             Action[] actions = super.getActions(context);
 
  997             ArrayList<Action> arrayList = 
new ArrayList<>();
 
  998             arrayList.addAll(Arrays.asList(actions));
 
 1001             } 
catch (TskCoreException ex) {
 
 1002                 LOGGER.log(Level.SEVERE, 
"Error gettung content by id", ex);
 
 1005             arrayList.add(approveActionInstance);
 
 1006             arrayList.add(rejectActionInstance);
 
 1008             return arrayList.toArray(
new Action[arrayList.size()]);
 
 1024                 event.artifacts.stream().map(BlackboardArtifact::getArtifactID).forEach(this::refreshKey);
 
 1035                 List<Long> list = 
new ArrayList<>();
 
 1038                         = 
"SELECT blackboard_artifacts.artifact_id "  
 1039                         + 
" FROM blackboard_artifacts "  
 1040                         + 
"      JOIN blackboard_attributes ON blackboard_artifacts.artifact_id = blackboard_attributes.artifact_id "  
 1041                         + 
" WHERE blackboard_artifacts.artifact_type_id = " + BlackboardArtifact.ARTIFACT_TYPE.TSK_ACCOUNT.getTypeID() 
 
 1042                         + 
"     AND blackboard_attributes.attribute_type_id = " + BlackboardAttribute.ATTRIBUTE_TYPE.TSK_CARD_NUMBER.getTypeID() 
 
 1043                         + 
"     AND blackboard_attributes.value_text >= '" + bin.getBINStart() + 
"' AND  blackboard_attributes.value_text < '" + (bin.getBINEnd() + 1) + 
"'"  
 1045                         + 
" ORDER BY blackboard_attributes.value_text"; 
 
 1046                 try (SleuthkitCase.CaseDbQuery results = skCase.executeQuery(query);
 
 1047                         ResultSet rs = results.getResultSet();) {
 
 1049                         list.add(rs.getLong(
"artifact_id")); 
 
 1051                 } 
catch (TskCoreException | SQLException ex) {
 
 1052                     LOGGER.log(Level.SEVERE, 
"Error querying for account artifacts.", ex); 
 
 1060                 if (skCase == null) {
 
 1065                     BlackboardArtifact art = skCase.getBlackboardArtifact(artifactID);
 
 1067                 } 
catch (TskCoreException ex) {
 
 1068                     LOGGER.log(Level.WARNING, 
"Error creating BlackboardArtifactNode for artifact with ID " + artifactID, ex);   
 
 1076             super(Children.LEAF);
 
 1078             setChildren(Children.createLazy(CreditCardNumberFactory::new));
 
 1079             setName(getBinRangeString());
 
 1080             updateDisplayName();
 
 1081             this.setIconBaseWithExtension(
"org/sleuthkit/autopsy/images/bank.png");   
 
 1082             reviewStatusBus.register(
this);
 
 1087             updateDisplayName();
 
 1092             updateDisplayName();
 
 1097                     = 
"SELECT count(blackboard_artifacts.artifact_id ) AS count"  
 1098                     + 
" FROM blackboard_artifacts "  
 1099                     + 
"      JOIN blackboard_attributes ON blackboard_artifacts.artifact_id = blackboard_attributes.artifact_id "  
 1100                     + 
" WHERE blackboard_artifacts.artifact_type_id = " + BlackboardArtifact.ARTIFACT_TYPE.TSK_ACCOUNT.getTypeID() 
 
 1101                     + 
"     AND blackboard_attributes.attribute_type_id = " + BlackboardAttribute.ATTRIBUTE_TYPE.TSK_CARD_NUMBER.getTypeID() 
 
 1102                     + 
"     AND blackboard_attributes.value_text >= '" + bin.getBINStart() + 
"' AND  blackboard_attributes.value_text < '" + (bin.getBINEnd() + 1) + 
"'"  
 1104             try (SleuthkitCase.CaseDbQuery results = skCase.executeQuery(query);
 
 1105                     ResultSet rs = results.getResultSet();) {
 
 1107                     setDisplayName(getBinRangeString() + 
" (" + rs.getLong(
"count") + 
")"); 
 
 1109             } 
catch (TskCoreException | SQLException ex) {
 
 1110                 LOGGER.log(Level.SEVERE, 
"Error querying for account artifacts.", ex); 
 
 1117             if (bin.getBINStart() == bin.getBINEnd()) {
 
 1118                 return Integer.toString(bin.getBINStart());
 
 1120                 return bin.getBINStart() + 
"-" + StringUtils.difference(bin.getBINStart() + 
"", bin.getBINEnd() + 
"");
 
 1131             return v.
visit(
this);
 
 1136             return getClass().getName();
 
 1140             Sheet.Set ss = s.get(Sheet.PROPERTIES);
 
 1142                 ss = Sheet.createPropertiesSet();
 
 1149         @NbBundle.Messages({
 
 1150             "Accounts.BINNode.binProperty.displayName=Bank Identifier Number",
 
 1151             "Accounts.BINNode.accountsProperty.displayName=Accounts",
 
 1152             "Accounts.BINNode.cardTypeProperty.displayName=Payment Card Type",
 
 1153             "Accounts.BINNode.schemeProperty.displayName=Credit Card Scheme",
 
 1154             "Accounts.BINNode.brandProperty.displayName=Brand",
 
 1155             "Accounts.BINNode.bankProperty.displayName=Bank",
 
 1156             "Accounts.BINNode.bankCityProperty.displayName=Bank City",
 
 1157             "Accounts.BINNode.bankCountryProperty.displayName=Bank Country",
 
 1158             "Accounts.BINNode.bankPhoneProperty.displayName=Bank Phone #",
 
 1159             "Accounts.BINNode.bankURLProperty.displayName=Bank URL",
 
 1160             "Accounts.BINNode.noDescription=no description"})
 
 1162             Sheet sheet = super.createSheet();
 
 1163             Sheet.Set properties = getPropertySet(sheet);
 
 1165             properties.put(
new NodeProperty<>(Bundle.Accounts_BINNode_binProperty_displayName(),
 
 1166                     Bundle.Accounts_BINNode_binProperty_displayName(),
 
 1167                     Bundle.Accounts_BINNode_noDescription(),
 
 1168                     getBinRangeString()));
 
 1169             properties.put(
new NodeProperty<>(Bundle.Accounts_BINNode_accountsProperty_displayName(),
 
 1170                     Bundle.Accounts_BINNode_accountsProperty_displayName(), Bundle.Accounts_BINNode_noDescription(),
 
 1174             if (bin.hasDetails()) {
 
 1175                 bin.
getCardType().ifPresent(cardType -> properties.put(
new NodeProperty<>(Bundle.Accounts_BINNode_cardTypeProperty_displayName(),
 
 1176                         Bundle.Accounts_BINNode_cardTypeProperty_displayName(), Bundle.Accounts_BINNode_noDescription(),
 
 1178                 bin.
getScheme().ifPresent(scheme -> properties.put(
new NodeProperty<>(Bundle.Accounts_BINNode_schemeProperty_displayName(),
 
 1179                         Bundle.Accounts_BINNode_schemeProperty_displayName(), Bundle.Accounts_BINNode_noDescription(),
 
 1181                 bin.
getBrand().ifPresent(brand -> properties.put(
new NodeProperty<>(Bundle.Accounts_BINNode_brandProperty_displayName(),
 
 1182                         Bundle.Accounts_BINNode_brandProperty_displayName(), Bundle.Accounts_BINNode_noDescription(),
 
 1184                 bin.
getBankName().ifPresent(bankName -> properties.put(
new NodeProperty<>(Bundle.Accounts_BINNode_bankProperty_displayName(),
 
 1185                         Bundle.Accounts_BINNode_bankProperty_displayName(), Bundle.Accounts_BINNode_noDescription(),
 
 1187                 bin.
getBankCity().ifPresent(bankCity -> properties.put(
new NodeProperty<>(Bundle.Accounts_BINNode_bankCityProperty_displayName(),
 
 1188                         Bundle.Accounts_BINNode_bankCityProperty_displayName(), Bundle.Accounts_BINNode_noDescription(),
 
 1190                 bin.
getCountry().ifPresent(country -> properties.put(
new NodeProperty<>(Bundle.Accounts_BINNode_bankCountryProperty_displayName(),
 
 1191                         Bundle.Accounts_BINNode_bankCountryProperty_displayName(), Bundle.Accounts_BINNode_noDescription(),
 
 1194                         Bundle.Accounts_BINNode_bankPhoneProperty_displayName(), Bundle.Accounts_BINNode_noDescription(),
 
 1196                 bin.
getBankURL().ifPresent(url -> properties.put(
new NodeProperty<>(Bundle.Accounts_BINNode_bankURLProperty_displayName(),
 
 1197                         Bundle.Accounts_BINNode_bankURLProperty_displayName(), Bundle.Accounts_BINNode_noDescription(),
 
 1214             hash = 97 * hash + this.binEnd;
 
 1215             hash = 97 * hash + this.binStart;
 
 1227             if (getClass() != obj.getClass()) {
 
 1231             if (this.binEnd != other.
binEnd) {
 
 1234             if (this.binStart != other.
binStart) {
 
 1251             this.binRange = binRange;
 
 1252             binStart = binRange.getBINstart();
 
 1253             binEnd = binRange.getBINend();
 
 1258             this.binRange = null;
 
 1275         boolean hasDetails() {
 
 1276             return binRange != null;
 
 1330             super(artifact, 
"org/sleuthkit/autopsy/images/credit-card.png");   
 
 1331             this.artifact = artifact;
 
 1332             setName(
"" + this.artifact.getArtifactID());
 
 1337             List<Action> actionsList = 
new ArrayList<>();
 
 1338             actionsList.addAll(Arrays.asList(super.getActions(context)));
 
 1340             actionsList.add(approveActionInstance);
 
 1341             actionsList.add(rejectActionInstance);
 
 1343             return actionsList.toArray(
new Action[actionsList.size()]);
 
 1348             Sheet sheet = super.createSheet();
 
 1349             Sheet.Set properties = sheet.get(Sheet.PROPERTIES);
 
 1350             if (properties == null) {
 
 1351                 properties = Sheet.createPropertiesSet();
 
 1352                 sheet.put(properties);
 
 1354             properties.put(
new NodeProperty<>(Bundle.Accounts_FileWithCCNNode_statusProperty_displayName(),
 
 1355                     Bundle.Accounts_FileWithCCNNode_statusProperty_displayName(),
 
 1356                     Bundle.Accounts_FileWithCCNNode_noDescription(),
 
 1357                     artifact.getReviewStatus().getDisplayName()));
 
 1365         @NbBundle.Messages(
"ToggleShowRejected.name=Show Rejected Results")
 
 1367             super(Bundle.ToggleShowRejected_name());
 
 1383             this.newStatus = newStatus;
 
 1392             List<String[]> selectedPaths = Utilities.actionsGlobalContext().lookupAll(Node.class).stream()
 
 1394                         String[] createPath;
 
 1400                         if (newStatus == BlackboardArtifact.ReviewStatus.REJECTED && showRejected == 
false) {
 
 1401                             List<Node> siblings = Arrays.asList(node.getParentNode().getChildren().getNodes());
 
 1402                             if (siblings.size() > 1) {
 
 1403                                 int indexOf = siblings.indexOf(node);
 
 1405                                 Node sibling = indexOf > 0
 
 1406                                         ? siblings.get(indexOf - 1)
 
 1407                                         : siblings.get(Integer.max(indexOf + 1, siblings.size() - 1));
 
 1408                                 createPath = NodeOp.createPath(sibling, null);
 
 1416                             createPath = NodeOp.createPath(node, null);
 
 1419                         return Arrays.copyOfRange(createPath, 1, createPath.length);
 
 1421                     .filter(Objects::nonNull)
 
 1422                     .collect(Collectors.toList());
 
 1425             final Collection<? extends BlackboardArtifact> artifacts = Utilities.actionsGlobalContext().lookupAll(BlackboardArtifact.class);
 
 1426             artifacts.forEach(artifact -> {
 
 1428                     skCase.setReviewStatus(artifact, newStatus);
 
 1429                 } 
catch (TskCoreException ex) {
 
 1430                     LOGGER.log(Level.SEVERE, 
"Error changing artifact review status.", ex); 
 
 1434             reviewStatusBus.post(
new ReviewStatusChangeEvent(artifacts, newStatus));
 
 1436             final DataResultTopComponent directoryListing = DirectoryTreeTopComponent.findInstance().getDirectoryListing();
 
 1437             final Node rootNode = directoryListing.getRootNode();
 
 1440             List<Node> toArray = 
new ArrayList<>();
 
 1441             selectedPaths.forEach(path -> {
 
 1443                     toArray.add(NodeOp.findPath(rootNode, path));
 
 1444                 } 
catch (NodeNotFoundException ex) {
 
 1449             directoryListing.setSelectedNodes(toArray.toArray(
new Node[toArray.size()]));
 
 1455         @NbBundle.Messages({
"ApproveAccountsAction.name=Approve Accounts"})
 
 1457             super(Bundle.ApproveAccountsAction_name(), BlackboardArtifact.ReviewStatus.APPROVED);
 
 1463         @NbBundle.Messages({
"RejectAccountsAction.name=Reject Accounts"})
 
 1465             super(Bundle.RejectAccountsAction_name(), BlackboardArtifact.ReviewStatus.REJECTED);
 
 1471         Collection<? extends BlackboardArtifact> artifacts;
 
 1472         BlackboardArtifact.ReviewStatus newReviewStatus;
 
 1474         public ReviewStatusChangeEvent(Collection<? extends BlackboardArtifact> artifacts, BlackboardArtifact.ReviewStatus newReviewStatus) {
 
 1475             this.artifacts = artifacts;
 
 1476             this.newReviewStatus = newReviewStatus;
 
List< CreditCardViewMode > createKeys()
final BlackboardArtifact.ReviewStatus newStatus
BlackboardArtifact.Type getBlackboardArtifactType()
void removeIngestModuleEventListener(final PropertyChangeListener listener)
Optional< Integer > getNumberLength()
Optional< String > getCountry()
Node[] createNodes(FileWithCCN key)
final BlackboardArtifact artifact
abstract Collection< X > createKeys()
static synchronized IngestManager getInstance()
List< Long > createKeys()
static final Logger LOGGER
Optional< String > getBankPhoneNumber()
Set< BlackboardArtifact.ReviewStatus > getStatuses()
Optional< String > getCountry()
Optional< String > getBankCity()
final String keywordSearchDocID
static List< Action > getActions(File file, boolean isArtifactSource)
Optional< String > getBankName()
static void removePropertyChangeListener(PropertyChangeListener listener)
final EventBus reviewStatusBus
String getRejectedArtifactFilterClause()
final String accountTypeName
Sheet.Set getPropertySet(Sheet s)
final RejectAccounts rejectActionInstance
List< Long > getArtifactIDs()
AccountArtifactNode(BlackboardArtifact artifact)
static synchronized BankIdentificationNumber getBINInfo(int bin)
Action[] getActions(boolean context)
Optional< String > getBankURL()
Node[] createNodes(BinResult key)
final ApproveAccounts approveActionInstance
T visit(DataSourcesNode in)
List< BinResult > createKeys()
void removeIngestJobEventListener(final PropertyChangeListener listener)
Optional< String > getScheme()
Node[] createNodes(String key)
final Set< BlackboardArtifact.ReviewStatus > statuses
Optional< String > getBrand()
Collection< Long > createKeys()
Node[] createNodes(Long t)
boolean equals(Object obj)
CreditCardNumberAccountTypeNode()
void addIngestJobEventListener(final PropertyChangeListener listener)
Optional< String > getBankURL()
String getkeywordSearchDocID()
ReviewStatusChangeEvent(Collection<?extends BlackboardArtifact > artifacts, BlackboardArtifact.ReviewStatus newReviewStatus)
Optional< Integer > getNumberLength()
BinResult(long count,@Nonnull BINRange binRange)
Action newToggleShowRejectedAction()
Optional< String > getBrand()
String getBinRangeString()
static void addPropertyChangeListener(PropertyChangeListener listener)
FileWithCCNNode(FileWithCCN key, Content content, Object[] lookupContents)
Action[] getActions(boolean context)
final List< Long > artifactIDs
DefaultAccountTypeNode(String accountTypeName)
Node[] createNodes(Long artifactID)
FileWithCCN(long objID, String solrDocID, List< Long > artifactIDs, long hits, Set< BlackboardArtifact.ReviewStatus > statuses)
List< FileWithCCN > createKeys()
void actionPerformed(ActionEvent e)
Optional< String > getBankCity()
Node[] createNodes(CreditCardViewMode key)
Optional< String > getCardType()
final FileWithCCN fileKey
BinResult(long count, int start, int end)
void addIngestModuleEventListener(final PropertyChangeListener listener)
static Case getCurrentCase()
List< String > createKeys()
boolean equals(Object obj)
ReviewStatusAction(String displayName, BlackboardArtifact.ReviewStatus newStatus)
void actionPerformed(ActionEvent e)
Optional< String > getScheme()
Optional< String > getBankName()
Optional< String > getBankPhoneNumber()
Optional< String > getCardType()
Accounts(SleuthkitCase skCase)