SOLR_DOCUMENT_IDs working in query; cleanup and comments in Accounts.java

This commit is contained in:
jmillman 2016-07-19 18:29:00 -04:00
parent ba308fb5da
commit 762f62bc7c
2 changed files with 224 additions and 123 deletions

View File

@ -22,6 +22,7 @@ import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener; import java.beans.PropertyChangeListener;
import java.sql.ResultSet; import java.sql.ResultSet;
import java.sql.SQLException; import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.Collections; import java.util.Collections;
import java.util.List; import java.util.List;
@ -37,7 +38,6 @@ import org.openide.nodes.ChildFactory;
import org.openide.nodes.Children; import org.openide.nodes.Children;
import org.openide.nodes.Node; import org.openide.nodes.Node;
import org.openide.nodes.Sheet; import org.openide.nodes.Sheet;
import org.openide.util.Exceptions;
import org.openide.util.NbBundle; import org.openide.util.NbBundle;
import org.openide.util.lookup.Lookups; import org.openide.util.lookup.Lookups;
import org.sleuthkit.autopsy.casemodule.Case; import org.sleuthkit.autopsy.casemodule.Case;
@ -75,6 +75,11 @@ public class Accounts extends Observable implements AutopsyVisitableItem {
return v.visit(this); return v.visit(this);
} }
/**
* Base class for factories that are also observers.
*
* @param <X> The type of keys used by this factory.
*/
private abstract class ObservingChildFactory<X> extends ChildFactory.Detachable<X> implements Observer { private abstract class ObservingChildFactory<X> extends ChildFactory.Detachable<X> implements Observer {
@Override @Override
@ -103,9 +108,9 @@ public class Accounts extends Observable implements AutopsyVisitableItem {
AccountsRootNode() { AccountsRootNode() {
super(Children.create(new AccountTypeFactory(), true)); super(Children.create(new AccountTypeFactory(), true));
super.setName("Accounts"); //NON-NLS super.setName("Accounts"); //NON-NLS
super.setDisplayName(Bundle.Accounts_RootNode_displayName()); super.setDisplayName(Bundle.Accounts_RootNode_displayName());
this.setIconBaseWithExtension("org/sleuthkit/autopsy/images/account_menu.png"); this.setIconBaseWithExtension("org/sleuthkit/autopsy/images/account_menu.png"); //NON-NLS
} }
@Override @Override
@ -126,7 +131,7 @@ public class Accounts extends Observable implements AutopsyVisitableItem {
private class AccountTypeFactory extends ObservingChildFactory<String> { private class AccountTypeFactory extends ObservingChildFactory<String> {
/* /*
* The pcl is in the class because it has the easiest mechanisms to add * The pcl is in this class because it has the easiest mechanisms to add
* and remove itself during its life cycles. * and remove itself during its life cycles.
*/ */
private final PropertyChangeListener pcl = new PropertyChangeListener() { private final PropertyChangeListener pcl = new PropertyChangeListener() {
@ -219,7 +224,7 @@ public class Accounts extends Observable implements AutopsyVisitableItem {
private AccountTypeNode(String accountTypeName) { private AccountTypeNode(String accountTypeName) {
super(Children.create(new ViewModeFactory(), true)); super(Children.create(new ViewModeFactory(), true));
super.setName(accountTypeName); super.setName(accountTypeName);
this.setIconBaseWithExtension("org/sleuthkit/autopsy/images/credit-cards.png"); //NON-NLS this.setIconBaseWithExtension("org/sleuthkit/autopsy/images/credit-cards.png"); //NON-NLS
} }
@Override @Override
@ -241,6 +246,10 @@ public class Accounts extends Observable implements AutopsyVisitableItem {
BY_BIN; BY_BIN;
} }
/**
* ChildFactory that makes nodes for the different account organizations (by
* file, by BIN)
*/
private class ViewModeFactory extends ObservingChildFactory<CreditCardViewMode> { private class ViewModeFactory extends ObservingChildFactory<CreditCardViewMode> {
@Override @Override
@ -262,20 +271,31 @@ public class Accounts extends Observable implements AutopsyVisitableItem {
} }
} }
public class ByFileNode extends DisplayableItemNode { /**
* Node that is the root of the "by file" accounts tree. Its children are
* FileWithCCNNodes.
*/
public class ByFileNode extends DisplayableItemNode implements Observer {
private final FileWithCCNFactory fileFactory;
private ByFileNode() { private ByFileNode() {
super(Children.create(new FileFactory(), true)); super(Children.LEAF);
setName("By File"); fileFactory = new FileWithCCNFactory();
setChildren(Children.create(fileFactory, true));
setName("By File"); //NON-NLS
updateDisplayName(); updateDisplayName();
this.setIconBaseWithExtension("org/sleuthkit/autopsy/images/file-icon.png"); //NON-NLS this.setIconBaseWithExtension("org/sleuthkit/autopsy/images/file-icon.png"); //NON-NLS
Accounts.this.addObserver(this);
} }
/** @NbBundle.Messages({
* TODO: Update the count in the display name "# {0} - number of children",
*/ "Accounts.ByFileNode.displayName=By File ({0})"})
private void updateDisplayName() { private void updateDisplayName() {
setDisplayName("By File"); ArrayList<FileWithCCN> keys = new ArrayList<>();
fileFactory.createKeys(keys);
setDisplayName(Bundle.Accounts_ByFileNode_displayName(keys.size()));
} }
@Override @Override
@ -287,16 +307,38 @@ public class Accounts extends Observable implements AutopsyVisitableItem {
public <T> T accept(DisplayableItemNodeVisitor<T> v) { public <T> T accept(DisplayableItemNodeVisitor<T> v) {
return v.visit(this); return v.visit(this);
} }
@Override
public void update(Observable o, Object arg) {
updateDisplayName();
}
} }
public class ByBINNode extends DisplayableItemNode { /**
* Node that is the root of the "By BIN" accounts tree. Its children are
* BINNodes.
*/
public class ByBINNode extends DisplayableItemNode implements Observer {
private final BINFactory binFactory;
private ByBINNode() { private ByBINNode() {
super(Children.create(new BINFactory(), true)); super(Children.LEAF);
setName("By BIN"); binFactory = new BINFactory();
setChildren(Children.create(binFactory, true));
setName("By BIN"); //NON-NLS
updateDisplayName(); updateDisplayName();
this.setIconBaseWithExtension("org/sleuthkit/autopsy/images/bank.png"); //NON-NLS this.setIconBaseWithExtension("org/sleuthkit/autopsy/images/bank.png"); //NON-NLS
Accounts.this.addObserver(this);
}
@NbBundle.Messages({
"# {0} - number of children",
"Accounts.ByBINNode.displayName=By BIN ({0})"})
private void updateDisplayName() {
ArrayList<BINInfo> keys = new ArrayList<>();
binFactory.createKeys(keys);
setDisplayName(Bundle.Accounts_ByBINNode_displayName(keys.size()));
} }
@Override @Override
@ -309,31 +351,29 @@ public class Accounts extends Observable implements AutopsyVisitableItem {
return v.visit(this); return v.visit(this);
} }
/** @Override
* TODO: Update the count in the display name public void update(Observable o, Object arg) {
*/ updateDisplayName();
private void updateDisplayName() {
setDisplayName("By BIN");
} }
} }
/**
* DataModel for a child of the ByFileNode. Represents a file(chunk) and its
* associated accounts.
*/
private static class FileWithCCN { private static class FileWithCCN {
final long objID; private final long objID;
final long chunkID; private final String solrDocumentId;
final List<Long> artifactIDS; private final List<Long> artifactIDS;
final long hits; private final long hits;
final long accepted;
private final String status; private final String status;
private FileWithCCN(long objID, long chunkID, List<Long> artifactIDS, long hits, long accepted, String status) { private FileWithCCN(long objID, String solrDocID, List<Long> artifactIDS, long hits, String status) {
this.objID = objID; this.objID = objID;
this.chunkID = chunkID; this.solrDocumentId = solrDocID;
this.artifactIDS = artifactIDS; this.artifactIDS = artifactIDS;
this.hits = hits; this.hits = hits;
this.accepted = accepted;
this.status = status; this.status = status;
} }
@ -341,8 +381,8 @@ public class Accounts extends Observable implements AutopsyVisitableItem {
return objID; return objID;
} }
public long getChunkID() { public String getSolrDocmentID() {
return chunkID; return solrDocumentId;
} }
public List<Long> getArtifactIDS() { public List<Long> getArtifactIDS() {
@ -353,10 +393,6 @@ public class Accounts extends Observable implements AutopsyVisitableItem {
return hits; return hits;
} }
public long getAccepted() {
return accepted;
}
public String getStatus() { public String getStatus() {
return status; return status;
} }
@ -386,38 +422,37 @@ public class Accounts extends Observable implements AutopsyVisitableItem {
} }
private class FileFactory extends ObservingChildFactory<FileWithCCN> { /**
* Factory for the children of the ByFiles Node.
*/
private class FileWithCCNFactory extends ObservingChildFactory<FileWithCCN> {
@Override @Override
protected boolean createKeys(List<FileWithCCN> list) { protected boolean createKeys(List<FileWithCCN> list) {
String query = String query =
"select distinct blackboard_artifacts.obj_id as obj_id," "SELECT blackboard_artifacts.obj_id," //NON-NLS
+ " blackboard_attributes.value_int32 as solr_document_id," + " blackboard_attributes.value_text AS solr_document_id, " //NON-NLS
+ " group_concat(blackboard_artifacts.artifact_id)," + " GROUP_CONCAT(blackboard_artifacts.artifact_id) AS artifact_IDs, " //NON-NLS
+ " count(blackboard_artifacts.artifact_id) as hits " + " COUNT( blackboard_artifacts.artifact_id) AS hits " //NON-NLS
// + " count (case when blackboard_artifacts.status like \"accepted\" then 1 else Null end) as accepted" + " FROM blackboard_artifacts " //NON-NLS
+ " from blackboard_artifacts, " + " LEFT JOIN blackboard_attributes ON blackboard_artifacts.artifact_id = blackboard_attributes.artifact_id " //NON-NLS
+ " blackboard_attributes " + " AND blackboard_attributes.attribute_type_id = " + BlackboardAttribute.ATTRIBUTE_TYPE.TSK_SOLR_DOCUMENT_ID.getTypeID() //NON-NLS
+ " where blackboard_artifacts.artifact_type_id = " + BlackboardArtifact.ARTIFACT_TYPE.TSK_CREDIT_CARD_ACCOUNT.getTypeID() + " WHERE blackboard_artifacts.artifact_type_id = " + BlackboardArtifact.ARTIFACT_TYPE.TSK_CREDIT_CARD_ACCOUNT.getTypeID() //NON-NLS
// + " and not (blackboard_artifacts.status like \"rejected\") " + " GROUP BY blackboard_artifacts.obj_id, solr_document_id " //NON-NLS
+ " and blackboard_artifacts.artifact_id = blackboard_attributes.artifact_id " + " ORDER BY hits DESC "; //NON-NLS
+ " and blackboard_attributes.attribute_type_id = " + BlackboardAttribute.ATTRIBUTE_TYPE.TSK_SOLR_DOCUMENT_ID.getTypeID()
+ " group by blackboard_artifacts.obj_id, solr_document_id"
+ " order by hits desc";//, accepted desc";
try (SleuthkitCase.CaseDbQuery results = skCase.executeQuery(query); try (SleuthkitCase.CaseDbQuery results = skCase.executeQuery(query);
ResultSet rs = results.getResultSet();) { ResultSet rs = results.getResultSet();) {
while (rs.next()) { while (rs.next()) {
list.add(new FileWithCCN( list.add(new FileWithCCN(
rs.getLong("obj_id"), rs.getLong("obj_id"), //NON-NLS
rs.getLong("solr_document_id"), rs.getString("solr_document_id"), //NON-NLS
unGroupConcat(rs.getString("group_concat(blackboard_artifacts.artifact_id)"), Long::valueOf), unGroupConcat(rs.getString("artifact_IDs"), Long::valueOf), //NON-NLS
rs.getLong("hits"), rs.getLong("hits"), //NON-NLS
0, "unreviewed")); //NON-NLS
"unreviewed"));
} }
} catch (TskCoreException | SQLException ex) { } catch (TskCoreException | SQLException ex) {
Exceptions.printStackTrace(ex); LOGGER.log(Level.SEVERE, "Error querying for files with ccn hits.", ex); //NON-NLS
return false;
} }
return true; return true;
} }
@ -427,6 +462,7 @@ public class Accounts extends Observable implements AutopsyVisitableItem {
try { try {
return new FileWithCCNNode(key, skCase.getAbstractFileById(key.getObjID())); return new FileWithCCNNode(key, skCase.getAbstractFileById(key.getObjID()));
} catch (TskCoreException ex) { } catch (TskCoreException ex) {
LOGGER.log(Level.SEVERE, "Error getting content for file with ccn hits.", ex); //NON-NLS
return null; return null;
} }
} }
@ -437,17 +473,26 @@ public class Accounts extends Observable implements AutopsyVisitableItem {
} }
} }
/**
* Node that represents a file or chunk of an unallocated space file.
*/
public class FileWithCCNNode extends DisplayableItemNode { public class FileWithCCNNode extends DisplayableItemNode {
private final FileWithCCN key; private final FileWithCCN fileKey;
private final Content content; private final String fileName;
@NbBundle.Messages({
"# {0} - raw file name",
"# {1} - solr chunk id",
"Accounts.FileWithCCNNode.unallocatedSpaceFile.displayName={0}_chunk_{1}"})
private FileWithCCNNode(FileWithCCN key, Content content) { private FileWithCCNNode(FileWithCCN key, Content content) {
super(Children.LEAF, Lookups.singleton(content)); super(Children.LEAF, Lookups.singleton(content));
this.fileKey = key;
setName(content.getName() + "_" + key.getChunkID()); this.fileName = (key.getSolrDocmentID() == null)
this.key = key; ? content.getName()
this.content = content; : Bundle.Accounts_FileWithCCNNode_unallocatedSpaceFile_displayName(content.getName(), StringUtils.substringAfter(key.getSolrDocmentID(), "_"));
setName(fileName);
setDisplayName(fileName);
} }
@Override @Override
@ -461,6 +506,11 @@ public class Accounts extends Observable implements AutopsyVisitableItem {
} }
@Override @Override
@NbBundle.Messages({
"Accounts.FileWithCCNNode.nameProperty.displayName=File",
"Accounts.FileWithCCNNode.accountsProperty.displayName=Accounts",
"Accounts.FileWithCCNNode.statusProperty.displayName=Status",
"Accounts.FileWithCCNNode.noDescription=no description"})
protected Sheet createSheet() { protected Sheet createSheet() {
Sheet s = super.createSheet(); Sheet s = super.createSheet();
Sheet.Set ss = s.get(Sheet.PROPERTIES); Sheet.Set ss = s.get(Sheet.PROPERTIES);
@ -469,25 +519,51 @@ public class Accounts extends Observable implements AutopsyVisitableItem {
s.put(ss); s.put(ss);
} }
ss.put(new NodeProperty<>("File Name", "File Name", "no description", content.getName() + "_" + key.getChunkID())); ss.put(new NodeProperty<>(Bundle.Accounts_FileWithCCNNode_nameProperty_displayName(),
ss.put(new NodeProperty<>("Hits", "Hits", "no description", key.getHits())); Bundle.Accounts_FileWithCCNNode_nameProperty_displayName(),
ss.put(new NodeProperty<>("Accepted", "Accepted", "no description", key.getAccepted())); Bundle.Accounts_FileWithCCNNode_noDescription(),
ss.put(new NodeProperty<>("Status", "Status", "no description", key.getStatus())); fileName));
ss.put(new NodeProperty<>(Bundle.Accounts_FileWithCCNNode_accountsProperty_displayName(),
Bundle.Accounts_FileWithCCNNode_accountsProperty_displayName(),
Bundle.Accounts_FileWithCCNNode_noDescription(),
fileKey.getHits()));
ss.put(new NodeProperty<>(Bundle.Accounts_FileWithCCNNode_statusProperty_displayName(),
Bundle.Accounts_FileWithCCNNode_statusProperty_displayName(),
Bundle.Accounts_FileWithCCNNode_noDescription(),
fileKey.getStatus()));
return s; return s;
} }
} }
public class BINNode extends DisplayableItemNode { /**
* Node that represents a BIN (Bank Identification Number)
*/
public class BINNode extends DisplayableItemNode implements Observer {
private final BIN bin; private final BINInfo bin;
private final AccountFactory accountFactory;
private BINNode(BIN key) { private BINNode(BINInfo bin) {
super(Children.create(new AccountFactory(key), true)); super(Children.LEAF);
this.bin = key; this.bin = bin;
setName(key.toString()); accountFactory = new AccountFactory(bin);
setDisplayName(key.getBIN().toString() + " (" + key.getCount() + ")"); setChildren(Children.create(accountFactory, true));
this.setIconBaseWithExtension("org/sleuthkit/autopsy/images/bank.png"); //NON-NLS setName(bin.toString());
updateDisplayName();
this.setIconBaseWithExtension("org/sleuthkit/autopsy/images/bank.png"); //NON-NLS
Accounts.this.addObserver(this);
}
@Override
public void update(Observable o, Object arg) {
updateDisplayName();
}
private void updateDisplayName() {
ArrayList<Long> keys = new ArrayList<>();
accountFactory.createKeys(keys);
setDisplayName(bin.getBIN().toString() + " (" + keys.size() + ")");
} }
@Override @Override
@ -501,6 +577,10 @@ public class Accounts extends Observable implements AutopsyVisitableItem {
} }
@Override @Override
@NbBundle.Messages({
"Accounts.BINNode.binProperty.displayName=Bank Identifier Number",
"Accounts.BINNode.accountsProperty.displayName=Accounts",
"Accounts.BINNode.noDescription=no description"})
protected Sheet createSheet() { protected Sheet createSheet() {
Sheet s = super.createSheet(); Sheet s = super.createSheet();
Sheet.Set ss = s.get(Sheet.PROPERTIES); Sheet.Set ss = s.get(Sheet.PROPERTIES);
@ -509,51 +589,66 @@ public class Accounts extends Observable implements AutopsyVisitableItem {
s.put(ss); s.put(ss);
} }
ss.put(new NodeProperty<>("Bank Identifier Number", "Bank Identifier Number", "no description", bin.getBIN())); ss.put(new NodeProperty<>(Bundle.Accounts_BINNode_binProperty_displayName(),
ss.put(new NodeProperty<>("Accounts ", "Accounts", "no description", bin.getCount())); Bundle.Accounts_BINNode_binProperty_displayName(),
Bundle.Accounts_BINNode_noDescription(),
bin.getBIN()));
ss.put(new NodeProperty<>(Bundle.Accounts_BINNode_accountsProperty_displayName(),
Bundle.Accounts_BINNode_accountsProperty_displayName(), Bundle.Accounts_BINNode_noDescription(),
bin.getCount()));
return s; return s;
} }
} }
private class BINFactory extends ObservingChildFactory<BIN> { /**
* Factory that generates the children of the ByBin node.
*/
private class BINFactory extends ObservingChildFactory<BINInfo> {
@Override @Override
protected boolean createKeys(List<BIN> list) { protected boolean createKeys(List<BINInfo> list) {
String query = String query =
"select substr(blackboard_attributes.value_text,1,6) as BIN, " "SELECT SUBSTR(blackboard_attributes.value_text,1,6) AS BIN, " //NON-NLS
+ " count(blackboard_artifacts.artifact_type_id) as count " + " COUNT(blackboard_artifacts.artifact_id) AS count " //NON-NLS
+ " from blackboard_artifacts," + " FROM blackboard_artifacts " //NON-NLS
+ " blackboard_attributes " + " JOIN blackboard_attributes ON blackboard_artifacts.artifact_id = blackboard_attributes.artifact_id" //NON-NLS
+ " where blackboard_artifacts.artifact_type_id = " + BlackboardArtifact.ARTIFACT_TYPE.TSK_CREDIT_CARD_ACCOUNT.getTypeID() + " WHERE blackboard_artifacts.artifact_type_id = " + BlackboardArtifact.ARTIFACT_TYPE.TSK_CREDIT_CARD_ACCOUNT.getTypeID() //NON-NLS
+ " and blackboard_artifacts.artifact_id = blackboard_attributes.artifact_id " + " AND blackboard_attributes.attribute_type_id = " + BlackboardAttribute.ATTRIBUTE_TYPE.TSK_ACCOUNT_NUMBER.getTypeID() //NON-NLS
+ " and blackboard_attributes.attribute_type_id = " + BlackboardAttribute.ATTRIBUTE_TYPE.TSK_ACCOUNT_NUMBER.getTypeID() + " GROUP BY BIN " //NON-NLS
+ " GROUP BY BIN " + " ORDER BY BIN "; //NON-NLS
+ " ORDER BY BIN ";
try (SleuthkitCase.CaseDbQuery results = skCase.executeQuery(query)) { try (SleuthkitCase.CaseDbQuery results = skCase.executeQuery(query)) {
ResultSet resultSet = results.getResultSet(); ResultSet resultSet = results.getResultSet();
while (resultSet.next()) { while (resultSet.next()) {
list.add(new BIN(Integer.valueOf(resultSet.getString("BIN")), list.add(new BINInfo(Integer.valueOf(resultSet.getString("BIN")), //NON-NLS
resultSet.getLong("count"))); resultSet.getLong("count"))); //NON-NLS
} }
} catch (TskCoreException | SQLException ex) { } catch (TskCoreException | SQLException ex) {
Exceptions.printStackTrace(ex); LOGGER.log(Level.SEVERE, "Error querying for BINs.", ex); //NON-NLS
return false;
} }
return true; return true;
} }
@Override @Override
protected Node createNodeForKey(BIN key) { protected Node createNodeForKey(BINInfo key) {
return new BINNode(key); return new BINNode(key);
} }
} }
private class BIN { /**
* Data model item to back the BINNodes in the tree. Has basic info about a
* BIN.
*/
private class BINInfo {
private final Integer bin; private final Integer bin;
/**
* The number of accounts with this BIN
*/
private final Long count; private final Long count;
private BIN(Integer bin, Long count) { private BINInfo(Integer bin, Long count) {
this.bin = bin; this.bin = bin;
this.count = count; this.count = count;
} }
@ -572,47 +667,47 @@ public class Accounts extends Observable implements AutopsyVisitableItem {
*/ */
private class AccountFactory extends ObservingChildFactory<Long> { private class AccountFactory extends ObservingChildFactory<Long> {
private final BIN bin; private final BINInfo bin;
private AccountFactory(BIN bin) { private AccountFactory(BINInfo bin) {
this.bin = bin; this.bin = bin;
} }
@Override @Override
protected boolean createKeys(List<Long> list) { protected boolean createKeys(List<Long> list) {
String query = String query =
"select blackboard_artifacts.artifact_id " "SELECT blackboard_artifacts.artifact_id " //NON-NLS
+ " from blackboard_artifacts, " + " FROM blackboard_artifacts " //NON-NLS
+ " blackboard_attributes " + " JOIN blackboard_attributes ON blackboard_artifacts.artifact_id = blackboard_attributes.artifact_id " //NON-NLS
+ " where blackboard_artifacts.artifact_type_id = " + BlackboardArtifact.ARTIFACT_TYPE.TSK_CREDIT_CARD_ACCOUNT.getTypeID() + " WHERE blackboard_artifacts.artifact_type_id = " + BlackboardArtifact.ARTIFACT_TYPE.TSK_CREDIT_CARD_ACCOUNT.getTypeID() //NON-NLS
+ " and blackboard_artifacts.artifact_id = blackboard_attributes.artifact_id " + " AND blackboard_attributes.attribute_type_id = " + BlackboardAttribute.ATTRIBUTE_TYPE.TSK_ACCOUNT_NUMBER.getTypeID() //NON-NLS
+ " and blackboard_attributes.attribute_type_id = " + BlackboardAttribute.ATTRIBUTE_TYPE.TSK_ACCOUNT_NUMBER.getTypeID() + " AND blackboard_attributes.value_text LIKE \"" + bin.getBIN() + "%\" " //NON-NLS
+ " and blackboard_attributes.value_text LIKE \"" + bin.getBIN() + "%\" " + " ORDER BY blackboard_attributes.value_text"; //NON-NLS
+ " ORDER BY blackboard_attributes.value_text";
try (SleuthkitCase.CaseDbQuery results = skCase.executeQuery(query); try (SleuthkitCase.CaseDbQuery results = skCase.executeQuery(query);
ResultSet rs = results.getResultSet();) { ResultSet rs = results.getResultSet();) {
while (rs.next()) { while (rs.next()) {
list.add(rs.getLong("artifact_id")); list.add(rs.getLong("artifact_id")); //NON-NLS
} }
} catch (TskCoreException | SQLException ex) { } catch (TskCoreException | SQLException ex) {
Exceptions.printStackTrace(ex); LOGGER.log(Level.SEVERE, "Error querying for account artifacts.", ex); //NON-NLS
return false;
} }
return true; return true;
} }
@Override @Override
protected Node createNodeForKey(Long id) { protected Node createNodeForKey(Long artifactID) {
if (skCase == null) { if (skCase == null) {
return null; return null;
} }
try { try {
BlackboardArtifact art = skCase.getBlackboardArtifact(id); BlackboardArtifact art = skCase.getBlackboardArtifact(artifactID);
return new BlackboardArtifactNode(art, "org/sleuthkit/autopsy/images/credit-card.png"); return new BlackboardArtifactNode(art, "org/sleuthkit/autopsy/images/credit-card.png"); //NON-NLS
} catch (TskCoreException ex) { } catch (TskCoreException ex) {
LOGGER.log(Level.WARNING, "TSK Exception occurred", ex); //NON-NLS LOGGER.log(Level.WARNING, "Error creating BlackboardArtifactNode for artifact with ID " + artifactID, ex); //NON-NLS
return null;
} }
return null;
} }
} }
} }

View File

@ -33,11 +33,13 @@ import org.apache.solr.client.solrj.SolrQuery;
import org.apache.solr.client.solrj.response.TermsResponse.Term; import org.apache.solr.client.solrj.response.TermsResponse.Term;
import org.sleuthkit.autopsy.coreutils.Logger; import org.sleuthkit.autopsy.coreutils.Logger;
import org.sleuthkit.autopsy.coreutils.Version; import org.sleuthkit.autopsy.coreutils.Version;
import org.sleuthkit.datamodel.AbstractFile;
import org.sleuthkit.datamodel.BlackboardArtifact; import org.sleuthkit.datamodel.BlackboardArtifact;
import org.sleuthkit.datamodel.BlackboardArtifact.ARTIFACT_TYPE; import org.sleuthkit.datamodel.BlackboardArtifact.ARTIFACT_TYPE;
import org.sleuthkit.datamodel.BlackboardAttribute; import org.sleuthkit.datamodel.BlackboardAttribute;
import org.sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE; import org.sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE;
import org.sleuthkit.datamodel.TskCoreException; import org.sleuthkit.datamodel.TskCoreException;
import org.sleuthkit.datamodel.TskData;
/** /**
* Performs a regular expression query to the SOLR/Lucene instance. * Performs a regular expression query to the SOLR/Lucene instance.
@ -185,12 +187,19 @@ final class TermComponentQuery implements KeywordSearchQuery {
//try to match it against the track 1 regex //try to match it against the track 1 regex
Matcher matcher = TRACK1_PATTERN.matcher(hit.getSnippet()); Matcher matcher = TRACK1_PATTERN.matcher(hit.getSnippet());
if (matcher.find()) { if (matcher.find()) {
parseTrack1Data(bba, matcher, hit); parseTrack1Data(bba, matcher);
} }
//then try to match it against the track 2 regex //then try to match it against the track 2 regex
matcher = TRACK2_PATTERN.matcher(hit.getSnippet()); matcher = TRACK2_PATTERN.matcher(hit.getSnippet());
if (matcher.find()) { if (matcher.find()) {
parseTrack2Data(bba, matcher, hit); parseTrack2Data(bba, matcher);
}
if (hit.getContent() instanceof AbstractFile) {
AbstractFile file = (AbstractFile) hit.getContent();
if (file.getType() == TskData.TSK_DB_FILES_TYPE_ENUM.UNUSED_BLOCKS
|| file.getType() == TskData.TSK_DB_FILES_TYPE_ENUM.UNALLOC_BLOCKS) {
bba.addAttribute(new BlackboardAttribute(SOLR_DOCUMENT_ID_TYPE, MODULE_NAME, hit.getSolrDocumentId()));
}
} }
} else { } else {
//make keyword hit artifact //make keyword hit artifact
@ -344,7 +353,7 @@ final class TermComponentQuery implements KeywordSearchQuery {
* @throws IllegalArgumentException * @throws IllegalArgumentException
* @throws TskCoreException * @throws TskCoreException
*/ */
static private void parseTrack2Data(BlackboardArtifact artifact, Matcher matcher, KeywordHit hit) throws IllegalArgumentException, TskCoreException { static private void parseTrack2Data(BlackboardArtifact artifact, Matcher matcher) throws IllegalArgumentException, TskCoreException {
//try to add all the attrributes common to track 1 and 2 //try to add all the attrributes common to track 1 and 2
addAttributeIfNotAlreadyCaptured(artifact, ATTRIBUTE_TYPE.TSK_ACCOUNT_NUMBER, "accountNumber", matcher); addAttributeIfNotAlreadyCaptured(artifact, ATTRIBUTE_TYPE.TSK_ACCOUNT_NUMBER, "accountNumber", matcher);
addAttributeIfNotAlreadyCaptured(artifact, ATTRIBUTE_TYPE.TSK_CREDIT_CARD_EXPIRATION, "expiration", matcher); addAttributeIfNotAlreadyCaptured(artifact, ATTRIBUTE_TYPE.TSK_CREDIT_CARD_EXPIRATION, "expiration", matcher);
@ -352,9 +361,6 @@ final class TermComponentQuery implements KeywordSearchQuery {
addAttributeIfNotAlreadyCaptured(artifact, ATTRIBUTE_TYPE.TSK_CREDIT_CARD_DISCRETIONARY, "discretionary", matcher); addAttributeIfNotAlreadyCaptured(artifact, ATTRIBUTE_TYPE.TSK_CREDIT_CARD_DISCRETIONARY, "discretionary", matcher);
addAttributeIfNotAlreadyCaptured(artifact, ATTRIBUTE_TYPE.TSK_CREDIT_CARD_LRC, "LRC", matcher); addAttributeIfNotAlreadyCaptured(artifact, ATTRIBUTE_TYPE.TSK_CREDIT_CARD_LRC, "LRC", matcher);
if (artifact.getAttribute(SOLR_DOCUMENT_ID_TYPE) == null) {
artifact.addAttribute(new BlackboardAttribute(SOLR_DOCUMENT_ID_TYPE, MODULE_NAME, hit.getSolrDocumentId()));
}
} }
/** /**
@ -368,9 +374,9 @@ final class TermComponentQuery implements KeywordSearchQuery {
* @throws IllegalArgumentException * @throws IllegalArgumentException
* @throws TskCoreException * @throws TskCoreException
*/ */
static private void parseTrack1Data(BlackboardArtifact artifact, Matcher matcher, KeywordHit hit) throws IllegalArgumentException, TskCoreException { static private void parseTrack1Data(BlackboardArtifact artifact, Matcher matcher) throws IllegalArgumentException, TskCoreException {
// track 1 has all the fields present in track 2 // track 1 has all the fields present in track 2
parseTrack2Data(artifact, matcher, hit); parseTrack2Data(artifact, matcher);
//plus it also has the account holders name //plus it also has the account holders name
addAttributeIfNotAlreadyCaptured(artifact, ATTRIBUTE_TYPE.TSK_NAME_PERSON, "name", matcher); addAttributeIfNotAlreadyCaptured(artifact, ATTRIBUTE_TYPE.TSK_NAME_PERSON, "name", matcher);
} }