19 package org.sleuthkit.autopsy.datamodel;
 
   21 import java.beans.PropertyChangeEvent;
 
   22 import java.beans.PropertyChangeListener;
 
   23 import java.sql.SQLException;
 
   24 import java.text.MessageFormat;
 
   25 import java.util.ArrayList;
 
   26 import java.util.Arrays;
 
   27 import java.util.Comparator;
 
   28 import java.util.EnumSet;
 
   29 import java.util.HashMap;
 
   30 import java.util.List;
 
   32 import java.util.Map.Entry;
 
   34 import java.util.concurrent.atomic.AtomicLong;
 
   35 import java.util.concurrent.atomic.AtomicReference;
 
   36 import java.util.logging.Level;
 
   37 import java.util.stream.Collectors;
 
   38 import java.util.stream.IntStream;
 
   39 import org.apache.commons.lang3.StringUtils;
 
   40 import org.apache.commons.lang3.tuple.Pair;
 
   41 import org.openide.nodes.AbstractNode;
 
   42 import org.openide.nodes.ChildFactory;
 
   43 import org.openide.nodes.Children;
 
   44 import org.openide.nodes.Node;
 
   45 import org.openide.nodes.Sheet;
 
   46 import org.openide.util.NbBundle;
 
   47 import org.openide.util.NbBundle.Messages;
 
   48 import org.openide.util.WeakListeners;
 
   49 import org.openide.util.lookup.Lookups;
 
   86     @NbBundle.Messages({
"ScoreContent_badFilter_text=Bad Items",
 
   87         "ScoreContent_susFilter_text=Suspicious Items"})
 
   90         BAD_ITEM_FILTER(0, 
"BAD_ITEM_FILTER",
 
   91                 Bundle.ScoreContent_badFilter_text()),
 
   92         SUS_ITEM_FILTER(1, 
"SUS_ITEM_FILTER",
 
   93                 Bundle.ScoreContent_susFilter_text());
 
  102             this.displayName = displayName;
 
  115             return this.displayName;
 
  120             return visitor.
visit(
this);
 
  141         this.filteringDSObjId = dsObjId;
 
  147     long filteringDataSourceObjId() {
 
  152     public <T> T accept(AutopsyItemVisitor<T> visitor) {
 
  153         return visitor.visit(
this);
 
  172             .map(evt -> evt.name())
 
  173             .collect(Collectors.toSet());
 
  186     private static PropertyChangeListener 
getPcl(
final Runnable onRefresh, 
final Runnable onRemove) {
 
  187         return (PropertyChangeEvent evt) -> {
 
  188             String eventType = evt.getPropertyName();
 
  193                     if (onRefresh != null) {
 
  203                 if (evt.getNewValue() == null && onRemove != null) {
 
  206             } 
else if (CASE_EVENTS_OF_INTEREST_STRS.contains(eventType)) {
 
  210                     if (onRefresh != null) {
 
  235         String query = 
" " + objIdAlias + 
" IN (SELECT tsk_aggregate_score.obj_id FROM tsk_aggregate_score WHERE " + aggregateScoreFilter + 
") ";
 
  237         if (filteringDSObjId > 0) {
 
  245             case SUS_ITEM_FILTER:
 
  248             case BAD_ITEM_FILTER:
 
  252                 throw new IllegalArgumentException(MessageFormat.format(
"Unsupported filter type to get suspect content: {0}", filter));
 
  265         return getFilter(filter, 
"obj_id", 
"data_source_obj_id", filteringDsObjId);
 
  277         return getFilter(filter, 
"artifacts.artifact_obj_id", 
"artifacts.data_source_obj_id", filteringDsObjId);
 
  288         String eventType = evt.getPropertyName();
 
  311         @NbBundle.Messages(
"ScoreContent_ScoreContentNode_name=Score")
 
  312         private static final String 
NAME = Bundle.ScoreContent_ScoreContentNode_name();
 
  315             super(Children.create(
new ScoreContentsChildren(skCase, datasourceObjId), 
true), Lookups.singleton(NAME));
 
  317             super.setDisplayName(NAME);
 
  318             this.setIconBaseWithExtension(
"org/sleuthkit/autopsy/images/red-circle-exclamation.png"); 
 
  328             return visitor.
visit(
this);
 
  333             "ScoreContent_createSheet_name_displayName=Name",
 
  334             "ScoreContent_createSheet_name_desc=no description"})
 
  336             Sheet sheet = super.createSheet();
 
  337             Sheet.Set sheetSet = sheet.get(Sheet.PROPERTIES);
 
  338             if (sheetSet == null) {
 
  339                 sheetSet = Sheet.createPropertiesSet();
 
  344                     Bundle.ScoreContent_createSheet_name_displayName(),
 
  345                     Bundle.ScoreContent_createSheet_name_desc(),
 
  352             return getClass().getName();
 
  370         private final PropertyChangeListener 
weakPcl = WeakListeners.propertyChange(pcl, null);
 
  376             this.datasourceObjId = dsObjId;
 
  408         protected boolean createKeys(List<ScoreContent.ScoreContentFilter> list) {
 
  410             typeNodeMap.values().forEach(nd -> nd.updateDisplayName());
 
  431                 super(Children.create(
new ScoreContentChildren(
filter, skCase, dsObjId), 
true), Lookups.singleton(
filter.getDisplayName()));
 
  433                 this.datasourceObjId = dsObjId;
 
  438                 super.setName(
filter.getName());
 
  440                 String tooltip = 
filter.getDisplayName();
 
  441                 this.setShortDescription(tooltip);
 
  443                     case SUS_ITEM_FILTER:
 
  444                         this.setIconBaseWithExtension(
"org/sleuthkit/autopsy/images/yellow-circle-yield.png"); 
 
  447                     case BAD_ITEM_FILTER:
 
  448                         this.setIconBaseWithExtension(
"org/sleuthkit/autopsy/images/red-circle-exclamation.png"); 
 
  455             void updateDisplayName() {
 
  461                     logger.log(Level.WARNING, 
"An error occurred while fetching file counts", ex);
 
  463                 super.setDisplayName(
filter.getDisplayName() + 
" (" + count + 
")");
 
  475                 AtomicLong retVal = 
new AtomicLong(0L);
 
  476                 AtomicReference<SQLException> exRef = 
new AtomicReference(null);
 
  478                 String query = 
" COUNT(tsk_aggregate_score.obj_id) AS count FROM tsk_aggregate_score WHERE\n" 
  480                         + ((datasourceObjId > 0) ? 
"AND tsk_aggregate_score.data_source_obj_id = \n" + datasourceObjId : 
"")
 
  481                         + 
" AND tsk_aggregate_score.obj_id IN\n" 
  482                         + 
" (SELECT tsk_files.obj_id AS obj_id FROM tsk_files UNION\n" 
  483                         + 
"     SELECT blackboard_artifacts.artifact_obj_id AS obj_id FROM blackboard_artifacts WHERE blackboard_artifacts.artifact_type_id IN\n" 
  484                         + 
"         (SELECT artifact_type_id FROM blackboard_artifact_types WHERE category_type = " + 
Category.
DATA_ARTIFACT.getID() + 
")) ";
 
  485                 sleuthkitCase.getCaseDbAccessManager().select(query, (rs) -> {
 
  488                             retVal.set(rs.getLong(
"count"));
 
  490                     } 
catch (SQLException ex) {
 
  495                 SQLException sqlEx = exRef.get();
 
  498                             MessageFormat.format(
"A sql exception occurred fetching results with query: SELECT {0}", query),
 
  507                 return visitor.
visit(
this);
 
  512                 "ScoreContent_createSheet_filterType_displayName=Type",
 
  513                 "ScoreContent_createSheet_filterType_desc=no description"})
 
  515                 Sheet sheet = super.createSheet();
 
  516                 Sheet.Set sheetSet = sheet.get(Sheet.PROPERTIES);
 
  517                 if (sheetSet == null) {
 
  518                     sheetSet = Sheet.createPropertiesSet();
 
  523                         Bundle.ScoreContent_createSheet_filterType_displayName(),
 
  524                         Bundle.ScoreContent_createSheet_filterType_desc(),
 
  525                         filter.getDisplayName()));
 
  548             private final PropertyChangeListener pcl = 
getPcl(
 
  549                     () -> ScoreContentChildren.this.refresh(
false),
 
  550                     () -> ScoreContentChildren.this.removeNotify());
 
  552             private final PropertyChangeListener weakPcl = WeakListeners.propertyChange(pcl, null);
 
  561                 super(filter.getName(), 
new ViewsKnownAndSlackFilter<>());
 
  563                 this.filter = filter;
 
  568             protected void onAdd() {
 
  576             protected void onRemove() {
 
  593             private List<Content> runFsQuery() {
 
  594                 List<Content> ret = 
new ArrayList<>();
 
  596                 String fileFilter = null;
 
  597                 String dataArtifactFilter = null;
 
  603                 } 
catch (TskCoreException | IllegalArgumentException e) {
 
  604                     logger.log(Level.SEVERE, MessageFormat.format(
 
  605                             "Error getting files for the deleted content view using file filter: {0} data artifact filter: {1}",
 
  606                             StringUtils.defaultString(fileFilter, 
"<null>"),
 
  607                             StringUtils.defaultString(dataArtifactFilter, 
"<null>")), e); 
 
  615             protected List<Content> makeKeys() {
 
  621                 return key.accept(
new ContentVisitor.Default<AbstractNode>() {
 
  622                     public FileNode visit(AbstractFile f) {
 
  623                         return new ScoreFileNode(f, false);
 
  626                     public FileNode visit(FsContent f) {
 
  627                         return new ScoreFileNode(f, 
false);
 
  631                     public FileNode visit(LayoutFile f) {
 
  632                         return new ScoreFileNode(f, 
false);
 
  636                     public FileNode visit(File f) {
 
  637                         return new ScoreFileNode(f, 
false);
 
  641                     public FileNode visit(Directory f) {
 
  642                         return new ScoreFileNode(f, 
false);
 
  646                     public FileNode visit(VirtualDirectory f) {
 
  647                         return new ScoreFileNode(f, 
false);
 
  651                     public AbstractNode visit(SlackFile sf) {
 
  652                         return new ScoreFileNode(sf, 
false);
 
  656                     public AbstractNode visit(LocalFile lf) {
 
  657                         return new ScoreFileNode(lf, 
false);
 
  661                     public AbstractNode visit(DerivedFile df) {
 
  662                         return new ScoreFileNode(df, 
false);
 
  666                     public AbstractNode visit(BlackboardArtifact ba) {
 
  667                         return new ScoreArtifactNode(ba);
 
  671                     protected AbstractNode defaultVisit(Content di) {
 
  672                         if (di instanceof AbstractFile) {
 
  673                             return visit((AbstractFile) di);
 
  675                             throw new UnsupportedOperationException(
"Not supported for this type of Displayable Item: " + di.toString());
 
  683     private static final String SOURCE_PROP = 
"Source";
 
  684     private static final String TYPE_PROP = 
"Type";
 
  685     private static final String PATH_PROP = 
"Path";
 
  686     private static final String DATE_PROP = 
"Created Date";
 
  689         Sheet sheet = 
new Sheet();
 
  690         Sheet.Set sheetSet = Sheet.createPropertiesSet();
 
  693         List<NodeProperty<?>> properties = 
new ArrayList<>();
 
  698                 StringUtils.defaultString(path)));
 
  706         if (StringUtils.isNotBlank(path)) {
 
  714         if (time != null && time > 0) {
 
  722         properties.forEach((property) -> {
 
  723             sheetSet.put(property);
 
  747         private static final Map<Integer, Integer> TIME_ATTR_IMPORTANCE = IntStream.range(0, TIME_ATTRS.size())
 
  748                 .mapToObj(idx -> Pair.of(TIME_ATTRS.get(idx).getTypeID(), idx))
 
  749                 .collect(Collectors.toMap(Entry::getKey, Entry::getValue, (v1, v2) -> v1));
 
  758                         .filter((attr) -> TIME_ATTR_IMPORTANCE.keySet().contains(attr.getAttributeType().getTypeID()))
 
  759                         .sorted(Comparator.comparing(attr -> TIME_ATTR_IMPORTANCE.get(attr.getAttributeType().getTypeID())))
 
  763                 if (timeAttr != null) {
 
  769                 logger.log(Level.WARNING, 
"An exception occurred while fetching time for artifact", ex);
 
  777                 return createScoreSheet(
 
  778                         this.content.getType().getDisplayName(),
 
  779                         this.content.getUniquePath(),
 
  780                         getTime(this.content)
 
  783                 logger.log(Level.WARNING, 
"An error occurred while fetching sheet data for score artifact.", ex);
 
  789     @Messages(
"ScoreContent_ScoreFileNode_type=File")
 
  795             super(af, directoryBrowseMode);
 
  801                 return createScoreSheet(
 
  802                         Bundle.ScoreContent_ScoreFileNode_type(),
 
  803                         this.content.getUniquePath(),
 
  804                         this.content.getCtime()
 
  807                 logger.log(Level.WARNING, 
"An error occurred while fetching sheet data for score file.", ex);
 
void registerForIngestModuleEvents()
boolean createKeys(List< ScoreContent.ScoreContentFilter > list)
final PropertyChangeListener pcl
void removeIngestModuleEventListener(final PropertyChangeListener listener)
static boolean isRefreshRequired(PropertyChangeEvent evt)
SleuthkitCase getSleuthkitCase()
static synchronized IngestManager getInstance()
public< T > T accept(AutopsyItemVisitor< T > visitor)
static String getFileFilter(ScoreContent.ScoreContentFilter filter, long filteringDsObjId)
static final Set< String > CASE_EVENTS_OF_INTEREST_STRS
synchronized Sheet createSheet()
Blackboard getBlackboard()
static final Type TSK_DATETIME_END
static final Set< IngestManager.IngestModuleEvent > INGEST_MODULE_EVENTS_OF_INTEREST
static Sheet createScoreSheet(String type, String path, Long time)
ScoreContent(SleuthkitCase skCase, long dsObjId)
ScoreContent(SleuthkitCase skCase)
final long filteringDSObjId
static final Type TSK_DATETIME_MODIFIED
Long getTime(BlackboardArtifact artifact)
static String getFormattedTime(long epochTime)
final Map< ScoreContentFilter, ScoreContentsChildren.ScoreContentNode > typeNodeMap
void unregisterEventListener()
static final Type TSK_DATETIME_PASSWORD_RESET
static final Type TSK_DATETIME_PASSWORD_FAIL
ScoreArtifactNode(BlackboardArtifact artifact)
static String getFilter(ScoreContent.ScoreContentFilter filter, String objIdAlias, String dsIdAlias, long filteringDSObjId)
static final Type TSK_DATETIME_ACCESSED
void removeIngestJobEventListener(final PropertyChangeListener listener)
Node createNodeForKey(ScoreContent.ScoreContentFilter key)
static long calculateItems(SleuthkitCase sleuthkitCase, ScoreContent.ScoreContentFilter filter, long datasourceObjId)
void addIngestJobEventListener(final PropertyChangeListener listener)
ScoreContentsChildren(SleuthkitCase skCase, long dsObjId)
static final Type TSK_DATETIME_CREATED
final long datasourceObjId
final ScoreContent.ScoreContentFilter filter
static final Logger logger
static String getDataArtifactFilter(ScoreContent.ScoreContentFilter filter, long filteringDsObjId)
T visit(DataSourceFilesNode in)
static final Type TSK_DATETIME
static final Type TSK_DATETIME_RCVD
List< BlackboardAttribute > getAttributes()
List< DataArtifact > getDataArtifactsWhere(String whereClause)
static final Type TSK_DATETIME_START
BLACKBOARD_ARTIFACT_TAG_ADDED
ScoreContentFilter(int id, String name, String displayName)
void addIngestModuleEventListener(final PropertyChangeListener listener)
List< AbstractFile > findAllFilesWhere(String sqlWhereClause)
static final Set< Case.Events > CASE_EVENTS_OF_INTEREST
boolean isRefreshRequired(PropertyChangeEvent evt)
synchronized static Logger getLogger(String name)
static final Type TSK_DATETIME_SENT
static final Set< IngestManager.IngestJobEvent > INGEST_JOB_EVENTS_OF_INTEREST
static Case getCurrentCaseThrows()
final long datasourceObjId
static void addEventTypeSubscriber(Set< Events > eventTypes, PropertyChangeListener subscriber)
ScoreFileNode(AbstractFile af, boolean directoryBrowseMode)
final RefreshThrottler refreshThrottler
static String getScoreFilter(ScoreContentFilter filter)
static final Type TSK_DATETIME_DELETED
static void removeEventTypeSubscriber(Set< Events > eventTypes, PropertyChangeListener subscriber)
synchronized Sheet createSheet()
final PropertyChangeListener weakPcl
BLACKBOARD_ARTIFACT_TAG_DELETED
static final String NO_DESCR
static PropertyChangeListener getPcl(final Runnable onRefresh, final Runnable onRemove)