Autopsy  4.7.0
Graphical digital forensics platform for The Sleuth Kit and other tools.
AbstractAbstractFileNode.java
Go to the documentation of this file.
1 /*
2  * Autopsy Forensic Browser
3  *
4  * Copyright 2011-2018 Basis Technology Corp.
5  * Contact: carrier <at> sleuthkit <dot> org
6  *
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  *
11  * http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  */
19 package org.sleuthkit.autopsy.datamodel;
20 
21 import java.beans.PropertyChangeEvent;
22 import java.beans.PropertyChangeListener;
23 import java.util.ArrayList;
24 import java.util.Arrays;
25 import java.util.EnumSet;
26 import java.util.List;
27 import java.util.Map;
28 import java.util.Set;
29 import java.util.logging.Level;
30 import java.util.stream.Collectors;
31 import javax.swing.Action;
32 import org.apache.commons.lang3.StringUtils;
33 import org.openide.nodes.Children;
34 import org.openide.nodes.Sheet;
35 import org.openide.util.NbBundle;
36 import org.openide.util.WeakListeners;
46 import static org.sleuthkit.autopsy.datamodel.Bundle.*;
49 import org.sleuthkit.datamodel.AbstractFile;
50 import org.sleuthkit.datamodel.Content;
51 import org.sleuthkit.datamodel.ContentTag;
52 import org.sleuthkit.datamodel.TskCoreException;
53 
59 public abstract class AbstractAbstractFileNode<T extends AbstractFile> extends AbstractContentNode<T> {
60 
61  private static final Logger logger = Logger.getLogger(AbstractAbstractFileNode.class.getName());
62  @NbBundle.Messages("AbstractAbstractFileNode.addFileProperty.desc=no description")
63  private static final String NO_DESCR = AbstractAbstractFileNode_addFileProperty_desc();
64 
65  private static final Set<Case.Events> CASE_EVENTS_OF_INTEREST = EnumSet.of(Case.Events.CURRENT_CASE,
67 
71  AbstractAbstractFileNode(T abstractFile) {
72  super(abstractFile);
73  String ext = abstractFile.getNameExtension();
74  if (StringUtils.isNotBlank(ext)) {
75  ext = "." + ext;
76  // If this is an archive file we will listen for ingest events
77  // that will notify us when new content has been identified.
78  if (FileTypeExtensions.getArchiveExtensions().contains(ext)) {
80  }
81  }
82  // Listen for case events so that we can detect when the case is closed
83  // or when tags are added.
85  }
86 
96  @Override
97  protected void finalize() throws Throwable {
98  super.finalize();
100  }
101 
102  private void removeListeners() {
105  }
106 
107  private final PropertyChangeListener pcl = (PropertyChangeEvent evt) -> {
108  String eventType = evt.getPropertyName();
109 
110  // Is this a content changed event?
111  if (eventType.equals(IngestManager.IngestModuleEvent.CONTENT_CHANGED.toString())) {
112  if ((evt.getOldValue() instanceof ModuleContentEvent) == false) {
113  return;
114  }
115  ModuleContentEvent moduleContentEvent = (ModuleContentEvent) evt.getOldValue();
116  if ((moduleContentEvent.getSource() instanceof Content) == false) {
117  return;
118  }
119  Content newContent = (Content) moduleContentEvent.getSource();
120 
121  // Does the event indicate that content has been added to *this* file?
122  if (getContent().getId() == newContent.getId()) {
123  // If so, refresh our children.
124  try {
125  Children parentsChildren = getParentNode().getChildren();
126  // We only want to refresh our parents children if we are in the
127  // data sources branch of the tree. The parent nodes in other
128  // branches of the tree (e.g. File Types and Deleted Files) do
129  // not need to be refreshed.
130  if (parentsChildren instanceof ContentChildren) {
131  ((ContentChildren) parentsChildren).refreshChildren();
132  parentsChildren.getNodesCount();
133  }
134  } catch (NullPointerException ex) {
135  // Skip
136  }
137  }
138  } else if (eventType.equals(Case.Events.CURRENT_CASE.toString())) {
139  if (evt.getNewValue() == null) {
140  // case was closed. Remove listeners so that we don't get called with a stale case handle
141  removeListeners();
142  }
143  } else if (eventType.equals(Case.Events.CONTENT_TAG_ADDED.toString())) {
145  if (event.getAddedTag().getContent().equals(content)) {
146  updateSheet();
147  }
148  } else if (eventType.equals(Case.Events.CONTENT_TAG_DELETED.toString())) {
150  if (event.getDeletedTagInfo().getContentID() == content.getId()) {
151  updateSheet();
152  }
153  }
154  };
155 
164  private final PropertyChangeListener weakPcl = WeakListeners.propertyChange(pcl, null);
165 
166  private void updateSheet() {
167  this.setSheet(createSheet());
168  }
169 
170  @NbBundle.Messages({"AbstractAbstractFileNode.nameColLbl=Name",
171  "AbstractAbstractFileNode.locationColLbl=Location",
172  "AbstractAbstractFileNode.modifiedTimeColLbl=Modified Time",
173  "AbstractAbstractFileNode.changeTimeColLbl=Change Time",
174  "AbstractAbstractFileNode.accessTimeColLbl=Access Time",
175  "AbstractAbstractFileNode.createdTimeColLbl=Created Time",
176  "AbstractAbstractFileNode.sizeColLbl=Size",
177  "AbstractAbstractFileNode.flagsDirColLbl=Flags(Dir)",
178  "AbstractAbstractFileNode.flagsMetaColLbl=Flags(Meta)",
179  "AbstractAbstractFileNode.modeColLbl=Mode",
180  "AbstractAbstractFileNode.useridColLbl=UserID",
181  "AbstractAbstractFileNode.groupidColLbl=GroupID",
182  "AbstractAbstractFileNode.metaAddrColLbl=Meta Addr.",
183  "AbstractAbstractFileNode.attrAddrColLbl=Attr. Addr.",
184  "AbstractAbstractFileNode.typeDirColLbl=Type(Dir)",
185  "AbstractAbstractFileNode.typeMetaColLbl=Type(Meta)",
186  "AbstractAbstractFileNode.knownColLbl=Known",
187  "AbstractAbstractFileNode.inHashsetsColLbl=In Hashsets",
188  "AbstractAbstractFileNode.md5HashColLbl=MD5 Hash",
189  "AbstractAbstractFileNode.objectId=Object ID",
190  "AbstractAbstractFileNode.mimeType=MIME Type",
191  "AbstractAbstractFileNode.extensionColLbl=Extension"})
193 
194  NAME(AbstractAbstractFileNode_nameColLbl()),
195  LOCATION(AbstractAbstractFileNode_locationColLbl()),
196  MOD_TIME(AbstractAbstractFileNode_modifiedTimeColLbl()),
197  CHANGED_TIME(AbstractAbstractFileNode_changeTimeColLbl()),
198  ACCESS_TIME(AbstractAbstractFileNode_accessTimeColLbl()),
199  CREATED_TIME(AbstractAbstractFileNode_createdTimeColLbl()),
200  SIZE(AbstractAbstractFileNode_sizeColLbl()),
201  FLAGS_DIR(AbstractAbstractFileNode_flagsDirColLbl()),
202  FLAGS_META(AbstractAbstractFileNode_flagsMetaColLbl()),
203  MODE(AbstractAbstractFileNode_modeColLbl()),
204  USER_ID(AbstractAbstractFileNode_useridColLbl()),
205  GROUP_ID(AbstractAbstractFileNode_groupidColLbl()),
206  META_ADDR(AbstractAbstractFileNode_metaAddrColLbl()),
207  ATTR_ADDR(AbstractAbstractFileNode_attrAddrColLbl()),
208  TYPE_DIR(AbstractAbstractFileNode_typeDirColLbl()),
209  TYPE_META(AbstractAbstractFileNode_typeMetaColLbl()),
210  KNOWN(AbstractAbstractFileNode_knownColLbl()),
211  HASHSETS(AbstractAbstractFileNode_inHashsetsColLbl()),
212  MD5HASH(AbstractAbstractFileNode_md5HashColLbl()),
213  ObjectID(AbstractAbstractFileNode_objectId()),
214  MIMETYPE(AbstractAbstractFileNode_mimeType()),
215  EXTENSION(AbstractAbstractFileNode_extensionColLbl());
216 
217  final private String displayString;
218 
219  private AbstractFilePropertyType(String displayString) {
220  this.displayString = displayString;
221  }
222 
223  @Override
224  public String toString() {
225  return displayString;
226  }
227  }
228 
236  static public void fillPropertyMap(Map<String, Object> map, AbstractFile content) {
237  map.put(NAME.toString(), getContentDisplayName(content));
238  map.put(LOCATION.toString(), getContentPath(content));
239  map.put(MOD_TIME.toString(), ContentUtils.getStringTime(content.getMtime(), content));
240  map.put(CHANGED_TIME.toString(), ContentUtils.getStringTime(content.getCtime(), content));
241  map.put(ACCESS_TIME.toString(), ContentUtils.getStringTime(content.getAtime(), content));
242  map.put(CREATED_TIME.toString(), ContentUtils.getStringTime(content.getCrtime(), content));
243  map.put(SIZE.toString(), content.getSize());
244  map.put(FLAGS_DIR.toString(), content.getDirFlagAsString());
245  map.put(FLAGS_META.toString(), content.getMetaFlagsAsString());
246  map.put(MODE.toString(), content.getModesAsString());
247  map.put(USER_ID.toString(), content.getUid());
248  map.put(GROUP_ID.toString(), content.getGid());
249  map.put(META_ADDR.toString(), content.getMetaAddr());
250  map.put(ATTR_ADDR.toString(), content.getAttrType().getValue() + "-" + content.getAttributeId());
251  map.put(TYPE_DIR.toString(), content.getDirType().getLabel());
252  map.put(TYPE_META.toString(), content.getMetaType().toString());
253  map.put(KNOWN.toString(), content.getKnown().getName());
254  map.put(HASHSETS.toString(), getHashSetHitsForFile(content));
255  map.put(MD5HASH.toString(), StringUtils.defaultString(content.getMd5Hash()));
256  map.put(ObjectID.toString(), content.getId());
257  map.put(MIMETYPE.toString(), StringUtils.defaultString(content.getMIMEType()));
258  map.put(EXTENSION.toString(), content.getNameExtension());
259  }
260 
261  @Override
262  public Action[] getActions(boolean context) {
263  List<Action> actionsList = new ArrayList<>();
264 
265  actionsList.addAll(Arrays.asList(super.getActions(true)));
266 
267  // Create the "Add/Edit Central Repository Comment" menu item if the enabled.
268  AbstractFile file = content;
269  if (EamDbUtil.useCentralRepo() && EamArtifactUtil.isSupportedAbstractFileType(file) && file.isFile()) {
271  }
272 
273  return actionsList.toArray(new Action[actionsList.size()]);
274  }
275 
283  @NbBundle.Messages("AbstractAbstractFileNode.tagsProperty.displayName=Tags")
284  protected void addTagProperty(Sheet.Set sheetSet) {
285  List<ContentTag> tags = new ArrayList<>();
286  try {
288  } catch (TskCoreException | NoCurrentCaseException ex) {
289  logger.log(Level.SEVERE, "Failed to get tags for content " + content.getName(), ex);
290  }
291  sheetSet.put(new NodeProperty<>("Tags", AbstractAbstractFileNode_tagsProperty_displayName(),
292  NO_DESCR, tags.stream().map(t -> t.getName().getDisplayName())
293  .distinct()
294  .collect(Collectors.joining(", "))));
295  }
296 
297  private static String getContentPath(AbstractFile file) {
298  try {
299  return file.getUniquePath();
300  } catch (TskCoreException ex) {
301  logger.log(Level.SEVERE, "Except while calling Content.getUniquePath() on " + file, ex); //NON-NLS
302  return ""; //NON-NLS
303  }
304  }
305 
306  static String getContentDisplayName(AbstractFile file) {
307  String name = file.getName();
308  switch (name) {
309  case "..":
310  return DirectoryNode.DOTDOTDIR;
311 
312  case ".":
313  return DirectoryNode.DOTDIR;
314  default:
315  return name;
316  }
317  }
318 
319  public static String getHashSetHitsForFile(AbstractFile file) {
320  try {
321  return StringUtils.join(file.getHashSetNames(), ", ");
322  } catch (TskCoreException tskCoreException) {
323  logger.log(Level.WARNING, "Error getting hashset hits: ", tskCoreException); //NON-NLS
324  return "";
325  }
326  }
327 }
void removeIngestModuleEventListener(final PropertyChangeListener listener)
static String getStringTime(long epochSeconds, TimeZone tzone)
static synchronized IngestManager getInstance()
List< ContentTag > getContentTagsByContent(Content content)
static void fillPropertyMap(Map< String, Object > map, AbstractFile content)
static AddEditCentralRepoCommentAction createAddEditCentralRepoCommentAction(AbstractFile file)
void addIngestModuleEventListener(final PropertyChangeListener listener)
synchronized static Logger getLogger(String name)
Definition: Logger.java:124
static void addEventTypeSubscriber(Set< Events > eventTypes, PropertyChangeListener subscriber)
Definition: Case.java:420
static void removeEventTypeSubscriber(Set< Events > eventTypes, PropertyChangeListener subscriber)
Definition: Case.java:465

Copyright © 2012-2016 Basis Technology. Generated on: Mon Jun 18 2018
This work is licensed under a Creative Commons Attribution-Share Alike 3.0 United States License.