Merge pull request #2365 from millmanorama/841-maintain-selection

841 maintain selection
This commit is contained in:
Richard Cordovano 2016-10-05 12:38:48 -04:00 committed by GitHub
commit 5e9d3b7082
64 changed files with 3478 additions and 2140 deletions

View File

@ -222,6 +222,10 @@
</dependency> </dependency>
</module-dependencies> </module-dependencies>
<public-packages> <public-packages>
<package>net.sf.sevenzipjbinding</package>
<package>net.sf.sevenzipjbinding.impl</package>
<package>net.sf.sevenzipjbinding.simple</package>
<package>net.sf.sevenzipjbinding.simple.impl</package>
<package>org.sleuthkit.autopsy.actions</package> <package>org.sleuthkit.autopsy.actions</package>
<package>org.sleuthkit.autopsy.casemodule</package> <package>org.sleuthkit.autopsy.casemodule</package>
<package>org.sleuthkit.autopsy.casemodule.events</package> <package>org.sleuthkit.autopsy.casemodule.events</package>

View File

@ -1,7 +1,7 @@
/* /*
* Autopsy Forensic Browser * Autopsy Forensic Browser
* *
* Copyright 2013-15 Basis Technology Corp. * Copyright 2011-2016 Basis Technology Corp.
* Contact: carrier <at> sleuthkit <dot> org * Contact: carrier <at> sleuthkit <dot> org
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
@ -19,8 +19,8 @@
package org.sleuthkit.autopsy.actions; package org.sleuthkit.autopsy.actions;
import java.awt.event.ActionEvent; import java.awt.event.ActionEvent;
import java.util.Collections; import java.util.Map;
import java.util.List; import java.util.TreeMap;
import java.util.logging.Level; import java.util.logging.Level;
import javax.swing.AbstractAction; import javax.swing.AbstractAction;
import javax.swing.JMenu; import javax.swing.JMenu;
@ -39,6 +39,7 @@ import org.sleuthkit.datamodel.TskCoreException;
*/ */
abstract class AddTagAction extends AbstractAction implements Presenter.Popup { abstract class AddTagAction extends AbstractAction implements Presenter.Popup {
private static final long serialVersionUID = 1L;
private static final String NO_COMMENT = ""; private static final String NO_COMMENT = "";
AddTagAction(String menuText) { AddTagAction(String menuText) {
@ -82,15 +83,16 @@ abstract class AddTagAction extends AbstractAction implements Presenter.Popup {
// to be reworked. // to be reworked.
private class TagMenu extends JMenu { private class TagMenu extends JMenu {
private static final long serialVersionUID = 1L;
TagMenu() { TagMenu() {
super(getActionDisplayName()); super(getActionDisplayName());
// Get the current set of tag names. // Get the current set of tag names.
TagsManager tagsManager = Case.getCurrentCase().getServices().getTagsManager(); TagsManager tagsManager = Case.getCurrentCase().getServices().getTagsManager();
List<TagName> tagNames = null; Map<String, TagName> tagNamesMap = null;
try { try {
tagNames = tagsManager.getAllTagNames(); tagNamesMap = new TreeMap<>(tagsManager.getDisplayNamesToTagNamesMap());
Collections.sort(tagNames);
} catch (TskCoreException ex) { } catch (TskCoreException ex) {
Logger.getLogger(TagsManager.class.getName()).log(Level.SEVERE, "Failed to get tag names", ex); //NON-NLS Logger.getLogger(TagsManager.class.getName()).log(Level.SEVERE, "Failed to get tag names", ex); //NON-NLS
} }
@ -102,11 +104,11 @@ abstract class AddTagAction extends AbstractAction implements Presenter.Popup {
// Each tag name in the current set of tags gets its own menu item in // Each tag name in the current set of tags gets its own menu item in
// the "Quick Tags" sub-menu. Selecting one of these menu items adds // the "Quick Tags" sub-menu. Selecting one of these menu items adds
// a tag with the associated tag name. // a tag with the associated tag name.
if (null != tagNames && !tagNames.isEmpty()) { if (null != tagNamesMap && !tagNamesMap.isEmpty()) {
for (final TagName tagName : tagNames) { for (Map.Entry<String, TagName> entry : tagNamesMap.entrySet()) {
JMenuItem tagNameItem = new JMenuItem(tagName.getDisplayName()); JMenuItem tagNameItem = new JMenuItem(entry.getKey());
tagNameItem.addActionListener((ActionEvent e) -> { tagNameItem.addActionListener((ActionEvent e) -> {
addTag(tagName, NO_COMMENT); getAndAddTag(entry.getKey(), entry.getValue(), NO_COMMENT);
}); });
quickTagMenu.add(tagNameItem); quickTagMenu.add(tagNameItem);
} }
@ -114,7 +116,7 @@ abstract class AddTagAction extends AbstractAction implements Presenter.Popup {
JMenuItem empty = new JMenuItem(NbBundle.getMessage(this.getClass(), "AddTagAction.noTags")); JMenuItem empty = new JMenuItem(NbBundle.getMessage(this.getClass(), "AddTagAction.noTags"));
empty.setEnabled(false); empty.setEnabled(false);
quickTagMenu.add(empty); quickTagMenu.add(empty);
} }
quickTagMenu.addSeparator(); quickTagMenu.addSeparator();
@ -143,5 +145,30 @@ abstract class AddTagAction extends AbstractAction implements Presenter.Popup {
}); });
add(tagAndCommentItem); add(tagAndCommentItem);
} }
/**
* Method to add to the action listener for each menu item. Allows a tag
* display name to be added to the menu with an action listener without
* having to instantiate a TagName object for it.
* When the method is called, the TagName object is created here if it
* doesn't already exist.
*
* @param tagDisplayName display name for the tag name
* @param tagName TagName object associated with the tag name,
* may be null
* @param comment comment for the content or artifact tag
*/
private void getAndAddTag(String tagDisplayName, TagName tagName, String comment) {
if (tagName == null) {
try {
tagName = Case.getCurrentCase().getServices().getTagsManager().addTagName(tagDisplayName);
} catch (TagsManager.TagNameAlreadyExistsException ex) {
Logger.getLogger(AddTagAction.class.getName()).log(Level.SEVERE, tagDisplayName + " already exists in database.", ex); //NON-NLS
} catch (TskCoreException ex) {
Logger.getLogger(AddTagAction.class.getName()).log(Level.SEVERE, "Error adding " + tagDisplayName + " tag name", ex); //NON-NLS
}
}
addTag(tagName, comment);
}
} }
} }

View File

@ -1,10 +1,10 @@
GetTagNameDialog.tagNameField.text= GetTagNameDialog.tagNameField.text=
GetTagNameDialog.cancelButton.text=Cancel GetTagNameDialog.cancelButton.text=Cancel
GetTagNameDialog.okButton.text=OK GetTagNameDialog.okButton.text=OK
GetTagNameDialog.preexistingLabel.text=Pre-existing Tags: GetTagNameDialog.preexistingLabel.text=Pre-existing Tag Names:
GetTagNameDialog.newTagPanel.border.title=New Tag GetTagNameDialog.newTagPanel.border.title=New Tag
GetTagNameDialog.tagNameLabel.text=Tag Name: GetTagNameDialog.tagNameLabel.text=Tag Name:
GetTagNameAndCommentDialog.newTagButton.text=New Tag GetTagNameAndCommentDialog.newTagButton.text=New Tag Name
GetTagNameAndCommentDialog.okButton.text=OK GetTagNameAndCommentDialog.okButton.text=OK
GetTagNameAndCommentDialog.commentText.toolTipText=Enter an optional tag comment or leave blank GetTagNameAndCommentDialog.commentText.toolTipText=Enter an optional tag comment or leave blank
GetTagNameAndCommentDialog.commentText.text= GetTagNameAndCommentDialog.commentText.text=
@ -42,7 +42,7 @@ GetTagNameDialog.createTag=Create Tag
GetTagNameDialog.cancelName=Cancel GetTagNameDialog.cancelName=Cancel
GetTagNameDialog.mustSupplyTtagName.msg=Must supply a tag name to continue. GetTagNameDialog.mustSupplyTtagName.msg=Must supply a tag name to continue.
GetTagNameDialog.tagNameErr=Tag Name GetTagNameDialog.tagNameErr=Tag Name
GetTagNameDialog.illegalChars.msg=The tag name contains illegal characters.\nCannot contain any of the following symbols\: \\ \: * ? " < > | GetTagNameDialog.illegalChars.msg=The tag name contains illegal characters.\nCannot contain any of the following symbols\: \\ \: * ? " < > | , ;
GetTagNameDialog.illegalCharsErr=Illegal Characters GetTagNameDialog.illegalCharsErr=Illegal Characters
GetTagNameDialog.unableToAddTagNameToCase.msg=Unable to add the {0} tag name to the case. GetTagNameDialog.unableToAddTagNameToCase.msg=Unable to add the {0} tag name to the case.
GetTagNameDialog.taggingErr=Tagging Error GetTagNameDialog.taggingErr=Tagging Error

View File

@ -28,7 +28,7 @@
<Group type="103" groupAlignment="0" attributes="0"> <Group type="103" groupAlignment="0" attributes="0">
<Group type="102" alignment="1" attributes="0"> <Group type="102" alignment="1" attributes="0">
<Component id="newTagButton" min="-2" max="-2" attributes="0"/> <Component id="newTagButton" min="-2" max="-2" attributes="0"/>
<EmptySpace pref="78" max="32767" attributes="0"/> <EmptySpace pref="48" max="32767" attributes="0"/>
<Component id="okButton" linkSize="1" min="-2" pref="67" max="-2" attributes="0"/> <Component id="okButton" linkSize="1" min="-2" pref="67" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/> <EmptySpace max="-2" attributes="0"/>
<Component id="cancelButton" linkSize="1" min="-2" max="-2" attributes="0"/> <Component id="cancelButton" linkSize="1" min="-2" max="-2" attributes="0"/>

View File

@ -21,8 +21,8 @@ package org.sleuthkit.autopsy.actions;
import java.awt.Window; import java.awt.Window;
import java.awt.event.ActionEvent; import java.awt.event.ActionEvent;
import java.awt.event.KeyEvent; import java.awt.event.KeyEvent;
import java.util.HashMap; import java.util.Map;
import java.util.List; import java.util.TreeMap;
import java.util.logging.Level; import java.util.logging.Level;
import javax.swing.AbstractAction; import javax.swing.AbstractAction;
import javax.swing.ActionMap; import javax.swing.ActionMap;
@ -43,7 +43,7 @@ public class GetTagNameAndCommentDialog extends JDialog {
private static final long serialVersionUID = 1L; private static final long serialVersionUID = 1L;
private static final String NO_TAG_NAMES_MESSAGE = NbBundle.getMessage(GetTagNameAndCommentDialog.class, private static final String NO_TAG_NAMES_MESSAGE = NbBundle.getMessage(GetTagNameAndCommentDialog.class,
"GetTagNameAndCommentDialog.noTags"); "GetTagNameAndCommentDialog.noTags");
private final HashMap<String, TagName> tagNames = new HashMap<>(); private final Map<String, TagName> tagNamesMap = new TreeMap<>();
private TagNameAndComment tagNameAndComment = null; private TagNameAndComment tagNameAndComment = null;
public static class TagNameAndComment { public static class TagNameAndComment {
@ -91,13 +91,18 @@ public class GetTagNameAndCommentDialog extends JDialog {
* dialog. * dialog.
*/ */
public static TagNameAndComment doDialog(Window owner) { public static TagNameAndComment doDialog(Window owner) {
return new GetTagNameAndCommentDialog(owner).tagNameAndComment; GetTagNameAndCommentDialog dialog = new GetTagNameAndCommentDialog(owner);
dialog.display();
return dialog.tagNameAndComment;
} }
private GetTagNameAndCommentDialog(Window owner) { private GetTagNameAndCommentDialog(Window owner) {
super(owner, super(owner,
NbBundle.getMessage(GetTagNameAndCommentDialog.class, "GetTagNameAndCommentDialog.createTag"), NbBundle.getMessage(GetTagNameAndCommentDialog.class, "GetTagNameAndCommentDialog.createTag"),
ModalityType.APPLICATION_MODAL); ModalityType.APPLICATION_MODAL);
}
private void display() {
initComponents(); initComponents();
// Set up the dialog to close when Esc is pressed. // Set up the dialog to close when Esc is pressed.
@ -106,6 +111,7 @@ public class GetTagNameAndCommentDialog extends JDialog {
inputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_ESCAPE, 0), cancelName); inputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_ESCAPE, 0), cancelName);
ActionMap actionMap = getRootPane().getActionMap(); ActionMap actionMap = getRootPane().getActionMap();
actionMap.put(cancelName, new AbstractAction() { actionMap.put(cancelName, new AbstractAction() {
private static final long serialVersionUID = 1L;
@Override @Override
public void actionPerformed(ActionEvent e) { public void actionPerformed(ActionEvent e) {
dispose(); dispose();
@ -114,24 +120,24 @@ public class GetTagNameAndCommentDialog extends JDialog {
// Populate the combo box with the available tag names and save the // Populate the combo box with the available tag names and save the
// tag name DTOs to be enable to return the one the user selects. // tag name DTOs to be enable to return the one the user selects.
// Tag name DTOs may be null (user tag names that have not been used do
// not exist in the database).
TagsManager tagsManager = Case.getCurrentCase().getServices().getTagsManager(); TagsManager tagsManager = Case.getCurrentCase().getServices().getTagsManager();
List<TagName> currentTagNames = null;
try { try {
currentTagNames = tagsManager.getAllTagNames(); tagNamesMap.putAll(tagsManager.getDisplayNamesToTagNamesMap());
} catch (TskCoreException ex) { } catch (TskCoreException ex) {
Logger.getLogger(GetTagNameAndCommentDialog.class.getName()).log(Level.SEVERE, "Failed to get tag names", ex); //NON-NLS Logger.getLogger(GetTagNameAndCommentDialog.class.getName()).log(Level.SEVERE, "Failed to get tag names", ex); //NON-NLS
} }
if (null != currentTagNames && currentTagNames.isEmpty()) { if (null != tagNamesMap && tagNamesMap.isEmpty()) {
tagCombo.addItem(NO_TAG_NAMES_MESSAGE); tagCombo.addItem(NO_TAG_NAMES_MESSAGE);
} else { } else {
for (TagName tagName : currentTagNames) { for (String tagDisplayName : tagNamesMap.keySet()) {
tagNames.put(tagName.getDisplayName(), tagName); tagCombo.addItem(tagDisplayName);
tagCombo.addItem(tagName.getDisplayName());
} }
} }
// Center and show the dialog box. // Center and show the dialog box.
this.setLocationRelativeTo(WindowManager.getDefault().getMainWindow()); this.setLocationRelativeTo(this.getOwner());
setVisible(true); setVisible(true);
} }
@ -197,7 +203,7 @@ public class GetTagNameAndCommentDialog extends JDialog {
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup() .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
.addComponent(newTagButton) .addComponent(newTagButton)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, 78, Short.MAX_VALUE) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, 48, Short.MAX_VALUE)
.addComponent(okButton, javax.swing.GroupLayout.PREFERRED_SIZE, 67, javax.swing.GroupLayout.PREFERRED_SIZE) .addComponent(okButton, javax.swing.GroupLayout.PREFERRED_SIZE, 67, javax.swing.GroupLayout.PREFERRED_SIZE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(cancelButton)) .addComponent(cancelButton))
@ -240,7 +246,18 @@ public class GetTagNameAndCommentDialog extends JDialog {
}// </editor-fold>//GEN-END:initComponents }// </editor-fold>//GEN-END:initComponents
private void okButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_okButtonActionPerformed private void okButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_okButtonActionPerformed
tagNameAndComment = new TagNameAndComment(tagNames.get((String) tagCombo.getSelectedItem()), commentText.getText()); String tagDisplayName = (String) tagCombo.getSelectedItem();
TagName tagNameFromCombo = tagNamesMap.get(tagDisplayName);
if (tagNameFromCombo == null) {
try {
tagNameFromCombo = Case.getCurrentCase().getServices().getTagsManager().addTagName(tagDisplayName);
} catch (TagsManager.TagNameAlreadyExistsException ex) {
Logger.getLogger(AddTagAction.class.getName()).log(Level.SEVERE, tagDisplayName + " already exists in database.", ex); //NON-NLS
} catch (TskCoreException ex) {
Logger.getLogger(AddTagAction.class.getName()).log(Level.SEVERE, "Error adding " + tagDisplayName + " tag name", ex); //NON-NLS
}
}
tagNameAndComment = new TagNameAndComment(tagNameFromCombo, commentText.getText());
dispose(); dispose();
}//GEN-LAST:event_okButtonActionPerformed }//GEN-LAST:event_okButtonActionPerformed
@ -257,7 +274,7 @@ public class GetTagNameAndCommentDialog extends JDialog {
private void newTagButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_newTagButtonActionPerformed private void newTagButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_newTagButtonActionPerformed
TagName newTagName = GetTagNameDialog.doDialog(this); TagName newTagName = GetTagNameDialog.doDialog(this);
if (newTagName != null) { if (newTagName != null) {
tagNames.put(newTagName.getDisplayName(), newTagName); tagNamesMap.put(newTagName.getDisplayName(), newTagName);
tagCombo.addItem(newTagName.getDisplayName()); tagCombo.addItem(newTagName.getDisplayName());
tagCombo.setSelectedItem(newTagName.getDisplayName()); tagCombo.setSelectedItem(newTagName.getDisplayName());
} }

View File

@ -1,7 +1,7 @@
/* /*
* Autopsy Forensic Browser * Autopsy Forensic Browser
* *
* Copyright 2013 Basis Technology Corp. * Copyright 2011-2016 Basis Technology Corp.
* Contact: carrier <at> sleuthkit <dot> org * Contact: carrier <at> sleuthkit <dot> org
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
@ -22,8 +22,9 @@ import java.awt.Window;
import java.awt.event.ActionEvent; import java.awt.event.ActionEvent;
import java.awt.event.KeyEvent; import java.awt.event.KeyEvent;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map;
import java.util.TreeMap;
import java.util.logging.Level; import java.util.logging.Level;
import javax.swing.AbstractAction; import javax.swing.AbstractAction;
import javax.swing.ActionMap; import javax.swing.ActionMap;
@ -44,8 +45,9 @@ import org.sleuthkit.datamodel.TskCoreException;
public class GetTagNameDialog extends JDialog { public class GetTagNameDialog extends JDialog {
private static final long serialVersionUID = 1L;
private static final String TAG_ICON_PATH = "org/sleuthkit/autopsy/images/tag-folder-blue-icon-16.png"; //NON-NLS private static final String TAG_ICON_PATH = "org/sleuthkit/autopsy/images/tag-folder-blue-icon-16.png"; //NON-NLS
private final HashMap<String, TagName> tagNames = new HashMap<>(); private final Map<String, TagName> tagNamesMap = new TreeMap<>();
private TagName tagName = null; private TagName tagName = null;
/** /**
@ -70,14 +72,19 @@ public class GetTagNameDialog extends JDialog {
* @return a TagName instance selected by the user, or null if the user * @return a TagName instance selected by the user, or null if the user
* canceled the dialog. * canceled the dialog.
*/ */
public static TagName doDialog(final Window owner) { public static TagName doDialog(Window owner) {
return new GetTagNameDialog(owner).tagName; GetTagNameDialog dialog = new GetTagNameDialog(owner);
dialog.display();
return dialog.tagName;
} }
private GetTagNameDialog(final Window owner) { private GetTagNameDialog(Window owner) {
super(owner, super(owner,
NbBundle.getMessage(GetTagNameDialog.class, "GetTagNameDialog.createTag"), NbBundle.getMessage(GetTagNameDialog.class, "GetTagNameDialog.createTag"),
ModalityType.APPLICATION_MODAL); ModalityType.APPLICATION_MODAL);
}
private void display() {
setIconImage(ImageUtilities.loadImage(TAG_ICON_PATH)); setIconImage(ImageUtilities.loadImage(TAG_ICON_PATH));
initComponents(); initComponents();
@ -87,6 +94,8 @@ public class GetTagNameDialog extends JDialog {
inputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_ESCAPE, 0), cancelName); inputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_ESCAPE, 0), cancelName);
ActionMap actionMap = getRootPane().getActionMap(); ActionMap actionMap = getRootPane().getActionMap();
actionMap.put(cancelName, new AbstractAction() { actionMap.put(cancelName, new AbstractAction() {
private static final long serialVersionUID = 1L;
@Override @Override
public void actionPerformed(ActionEvent e) { public void actionPerformed(ActionEvent e) {
cancelButtonActionPerformed(e); cancelButtonActionPerformed(e);
@ -96,56 +105,38 @@ public class GetTagNameDialog extends JDialog {
// Get the current set of tag names and hash them for a speedy lookup in // Get the current set of tag names and hash them for a speedy lookup in
// case the user chooses an existing tag name from the tag names table. // case the user chooses an existing tag name from the tag names table.
TagsManager tagsManager = Case.getCurrentCase().getServices().getTagsManager(); TagsManager tagsManager = Case.getCurrentCase().getServices().getTagsManager();
List<TagName> currentTagNames = null;
try { try {
currentTagNames = tagsManager.getAllTagNames(); tagNamesMap.putAll(tagsManager.getDisplayNamesToTagNamesMap());
} catch (TskCoreException ex) { } catch (TskCoreException ex) {
Logger.getLogger(GetTagNameDialog.class.getName()).log(Level.SEVERE, "Failed to get tag names", ex); //NON-NLS Logger.getLogger(GetTagNameDialog.class.getName()).log(Level.SEVERE, "Failed to get tag names", ex); //NON-NLS
} }
if (null != currentTagNames) {
for (TagName name : currentTagNames) {
this.tagNames.put(name.getDisplayName(), name);
}
} else {
currentTagNames = new ArrayList<>();
}
// Populate the tag names table. // Populate the tag names table.
tagsTable.setModel(new TagsTableModel(currentTagNames)); tagsTable.setModel(new TagsTableModel(new ArrayList<>(tagNamesMap.keySet())));
tagsTable.setTableHeader(null); tagsTable.setTableHeader(null);
tagsTable.setCellSelectionEnabled(false); tagsTable.setCellSelectionEnabled(false);
tagsTable.setFocusable(false); tagsTable.setFocusable(false);
tagsTable.setRowHeight(tagsTable.getRowHeight() + 5); tagsTable.setRowHeight(tagsTable.getRowHeight() + 5);
// Center and show the dialog box. // Center and show the dialog box.
this.setLocationRelativeTo(owner); this.setLocationRelativeTo(this.getOwner());
setVisible(true); setVisible(true);
} }
private boolean containsIllegalCharacters(String content) {
return (content.contains("\\")
|| content.contains(":")
|| content.contains("*")
|| content.contains("?")
|| content.contains("\"")
|| content.contains("<")
|| content.contains(">")
|| content.contains("|"));
}
private class TagsTableModel extends AbstractTableModel { private class TagsTableModel extends AbstractTableModel {
private final ArrayList<TagName> tagNames = new ArrayList<>(); private static final long serialVersionUID = 1L;
private final ArrayList<String> tagDisplayNames = new ArrayList<>();
TagsTableModel(List<TagName> tagNames) { TagsTableModel(List<String> tagDisplayNames) {
for (TagName tagName : tagNames) { for (String tagDisplayName : tagDisplayNames) {
this.tagNames.add(tagName); this.tagDisplayNames.add(tagDisplayName);
} }
} }
@Override @Override
public int getRowCount() { public int getRowCount() {
return tagNames.size(); return tagDisplayNames.size();
} }
@Override @Override
@ -160,7 +151,7 @@ public class GetTagNameDialog extends JDialog {
@Override @Override
public String getValueAt(int rowIndex, int columnIndex) { public String getValueAt(int rowIndex, int columnIndex) {
return tagNames.get(rowIndex).getDisplayName(); return tagDisplayNames.get(rowIndex);
} }
} }
@ -305,13 +296,13 @@ public class GetTagNameDialog extends JDialog {
"GetTagNameDialog.mustSupplyTtagName.msg"), "GetTagNameDialog.mustSupplyTtagName.msg"),
NbBundle.getMessage(this.getClass(), "GetTagNameDialog.tagNameErr"), NbBundle.getMessage(this.getClass(), "GetTagNameDialog.tagNameErr"),
JOptionPane.ERROR_MESSAGE); JOptionPane.ERROR_MESSAGE);
} else if (containsIllegalCharacters(tagDisplayName)) { } else if (TagsManager.containsIllegalCharacters(tagDisplayName)) {
JOptionPane.showMessageDialog(null, JOptionPane.showMessageDialog(null,
NbBundle.getMessage(this.getClass(), "GetTagNameDialog.illegalChars.msg"), NbBundle.getMessage(this.getClass(), "GetTagNameDialog.illegalChars.msg"),
NbBundle.getMessage(this.getClass(), "GetTagNameDialog.illegalCharsErr"), NbBundle.getMessage(this.getClass(), "GetTagNameDialog.illegalCharsErr"),
JOptionPane.ERROR_MESSAGE); JOptionPane.ERROR_MESSAGE);
} else { } else {
tagName = tagNames.get(tagDisplayName); tagName = tagNamesMap.get(tagDisplayName);
if (tagName == null) { if (tagName == null) {
try { try {
tagName = Case.getCurrentCase().getServices().getTagsManager().addTagName(tagDisplayName); tagName = Case.getCurrentCase().getServices().getTagsManager().addTagName(tagDisplayName);
@ -326,7 +317,7 @@ public class GetTagNameDialog extends JDialog {
JOptionPane.ERROR_MESSAGE); JOptionPane.ERROR_MESSAGE);
tagName = null; tagName = null;
} catch (TagsManager.TagNameAlreadyExistsException ex) { } catch (TagsManager.TagNameAlreadyExistsException ex) {
Logger.getLogger(AddTagAction.class.getName()).log(Level.SEVERE, "Error adding " + tagDisplayName + " tag name", ex); //NON-NLS Logger.getLogger(AddTagAction.class.getName()).log(Level.SEVERE, tagDisplayName + " already exists in database.", ex); //NON-NLS
JOptionPane.showMessageDialog(null, JOptionPane.showMessageDialog(null,
NbBundle.getMessage(this.getClass(), NbBundle.getMessage(this.getClass(),
"GetTagNameDialog.tagNameAlreadyDef.msg", "GetTagNameDialog.tagNameAlreadyDef.msg",

View File

@ -1,9 +1,18 @@
TagsManager.addContentTag.exception.beginByteOffsetOOR.msg=beginByteOffset \= {0} out of content size range (0 - {1}) OptionsCategory_Name_TagNamesOptions=Tags
TagsManager.addContentTag.exception.endByteOffsetOOR.msg=endByteOffset \= {0} out of content size range (0 - {1}) OptionsCategory_TagNames=TagNames
TagsManager.addContentTag.exception.endLTbegin.msg=endByteOffset < beginByteOffset
TagsManager.predefTagNames.bookmark.text=Bookmark
TagsManager.addContentTag.noCaseWarning=Failed to publish new content tag event. There is no case open.
TagsManager.deleteContentTag.noCaseWarning=Failed to publish content tag deleted event. There is no case open.
TagsManager.addBlackboardArtifactTag.noCaseWarning=Failed to publish new blackboard artifact tag event. There is no case open.
TagsManager.deleteBlackboardArtifactTag.noCaseWarning=Failed to publish blackboard artifact tag deleted event. There is no case open.
Blackboard.unableToIndexArtifact.error.msg=Unable to index blackboard artifact {0} Blackboard.unableToIndexArtifact.error.msg=Unable to index blackboard artifact {0}
NewUserTagNameDialog.title.text=New Tag Name
NewUserTagNameDialog.JOptionPane.tagNameIllegalCharacters.message=Tag name may not contain any of the following symbols\: \\ \: * ? " < > | , ;
NewUserTagNameDialog.JOptionPane.tagNameIllegalCharacters.title=Invalid character in tag name
TagNamesSettingsPanel.JOptionPane.tagNameAlreadyExists.message=The tag name already exists in your settings
TagNamesSettingsPanel.JOptionPane.tagNameAlreadyExists.title=Tag name already exists
NewUserTagNameDialog.JOptionPane.tagNameEmpty.message=The tag name cannot be empty
NewUserTagNameDialog.JOptionPane.tagNameEmpty.title=Empty tag name
TagOptionsPanel.tagTypesListLabel.text=Tag Names:
TagOptionsPanel.panelDescriptionLabel.text=Autopsy keeps a list of the tag names you have created in the past. Add more or delete them here.
NewTagNameDialog.okButton.text=OK
NewTagNameDialog.cancelButton.text=Cancel
NewTagNameDialog.tagNameTextField.text=
NewTagNameDialog.newTagNameLabel.text=New Tag Name:
TagOptionsPanel.deleteTagNameButton.text=Delete Tag Name
TagOptionsPanel.newTagNameButton.text=New Tag Name

View File

@ -1,9 +1,2 @@
TagsManager.addContentTag.exception.beginByteOffsetOOR.msg=beginByteOffset \= {0} \u30b3\u30f3\u30c6\u30f3\u30c4\u30b5\u30a4\u30ba\u7bc4\u56f2(0 - {1})\u306e\u5916\u3067\u3059
TagsManager.addContentTag.exception.endByteOffsetOOR.msg=endByteOffset \= {0} \u30b3\u30f3\u30c6\u30f3\u30c4\u30b5\u30a4\u30ba\u7bc4\u56f2(0 - {1})\u306e\u5916\u3067\u3059
TagsManager.addContentTag.exception.endLTbegin.msg=endByteOffset < beginByteOffset
TagsManager.predefTagNames.bookmark.text=\u30d6\u30c3\u30af\u30de\u30fc\u30af TagsManager.predefTagNames.bookmark.text=\u30d6\u30c3\u30af\u30de\u30fc\u30af
TagsManager.addContentTag.noCaseWarning=\u65b0\u3057\u3044\u30bf\u30b0\u30a4\u30d9\u30f3\u30c8\u3092\u30d1\u30d6\u30ea\u30c3\u30b7\u30e5\u3067\u304d\u307e\u305b\u3093\u3067\u3057\u305f\u3002\u958b\u3044\u3066\u3044\u308b\u30b1\u30fc\u30b9\u304c\u3042\u308a\u307e\u305b\u3093\u3002
TagsManager.deleteContentTag.noCaseWarning=\u524a\u9664\u3055\u308c\u305f\u30a4\u30d9\u30f3\u30c8\u306e\u30bf\u30b0\u306e\u30b3\u30f3\u30c6\u30f3\u30c4\u3092\u30d1\u30d6\u30ea\u30c3\u30b7\u30e5\u3067\u304d\u307e\u305b\u3093\u3067\u3057\u305f\u3002\u958b\u3044\u3066\u3044\u308b\u30b1\u30fc\u30b9\u304c\u3042\u308a\u307e\u305b\u3093\u3002
TagsManager.addBlackboardArtifactTag.noCaseWarning=\u30a4\u30d9\u30f3\u30c8\u306e\u30bf\u30b0\u306e\u65b0\u3057\u3044blackboard\u30a2\u30fc\u30c6\u30a3\u30d5\u30a1\u30af\u30c8\u3092\u30d1\u30d6\u30ea\u30c3\u30b7\u30e5\u3067\u304d\u307e\u305b\u3093\u3067\u3057\u305f\u3002\u958b\u3044\u3066\u3044\u308b\u30b1\u30fc\u30b9\u304c\u3042\u308a\u307e\u305b\u3093\u3002
TagsManager.deleteBlackboardArtifactTag.noCaseWarning=\u524a\u9664\u3055\u308c\u305f\u30a4\u30d9\u30f3\u30c8\u306e\u30bf\u30b0\u306e\u65b0\u3057\u3044blackboard\u30a2\u30fc\u30c6\u30a3\u30d5\u30a1\u30af\u30c8\u3092\u30d1\u30d6\u30ea\u30c3\u30b7\u30e5\u3067\u304d\u307e\u305b\u3093\u3067\u3057\u305f\u3002\u958b\u3044\u3066\u3044\u308b\u30b1\u30fc\u30b9\u304c\u3042\u308a\u307e\u305b\u3093\u3002
Blackboard.unableToIndexArtifact.error.msg=blackboard\u30a2\u30fc\u30c6\u30a3\u30d5\u30a1\u30af\u30c8{0}\u3092\u30a4\u30f3\u30c7\u30c3\u30af\u30b9\u3067\u304d\u307e\u305b\u3093\u3067\u3057\u305f\u3002 Blackboard.unableToIndexArtifact.error.msg=blackboard\u30a2\u30fc\u30c6\u30a3\u30d5\u30a1\u30af\u30c8{0}\u3092\u30a4\u30f3\u30c7\u30c3\u30af\u30b9\u3067\u304d\u307e\u305b\u3093\u3067\u3057\u305f\u3002

View File

@ -27,6 +27,7 @@ import java.io.IOException;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collection; import java.util.Collection;
import java.util.List; import java.util.List;
import java.util.logging.Level;
import org.openide.util.NbBundle; import org.openide.util.NbBundle;
import org.sleuthkit.autopsy.datamodel.VirtualDirectoryNode; import org.sleuthkit.autopsy.datamodel.VirtualDirectoryNode;
import org.sleuthkit.autopsy.ingest.IngestServices; import org.sleuthkit.autopsy.ingest.IngestServices;
@ -43,6 +44,7 @@ import org.sleuthkit.datamodel.VirtualDirectory;
import org.sleuthkit.datamodel.LocalFilesDataSource; import org.sleuthkit.datamodel.LocalFilesDataSource;
import org.sleuthkit.datamodel.TskDataException; import org.sleuthkit.datamodel.TskDataException;
import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.StringUtils;
import org.sleuthkit.autopsy.coreutils.Logger;
import org.sleuthkit.datamodel.CarvingResult; import org.sleuthkit.datamodel.CarvingResult;
import org.sleuthkit.datamodel.TskData; import org.sleuthkit.datamodel.TskData;
@ -53,6 +55,7 @@ import org.sleuthkit.datamodel.TskData;
*/ */
public class FileManager implements Closeable { public class FileManager implements Closeable {
private static final Logger LOGGER = Logger.getLogger(FileManager.class.getName());
private SleuthkitCase caseDb; private SleuthkitCase caseDb;
/** /**
@ -427,7 +430,11 @@ public class FileManager implements Closeable {
} catch (TskCoreException ex) { } catch (TskCoreException ex) {
if (null != trans) { if (null != trans) {
trans.rollback(); try {
trans.rollback();
} catch (TskCoreException ex2) {
LOGGER.log(Level.SEVERE, String.format("Failed to rollback transaction after exception: %s", ex.getMessage()), ex2);
}
} }
throw ex; throw ex;
} }

View File

@ -0,0 +1,98 @@
<?xml version="1.0" encoding="UTF-8" ?>
<Form version="1.5" maxVersion="1.9" type="org.netbeans.modules.form.forminfo.JDialogFormInfo">
<Properties>
<Property name="defaultCloseOperation" type="int" value="2"/>
</Properties>
<SyntheticProperties>
<SyntheticProperty name="formSizePolicy" type="int" value="1"/>
<SyntheticProperty name="generateCenter" type="boolean" value="false"/>
</SyntheticProperties>
<AuxValues>
<AuxValue name="FormSettings_autoResourcing" type="java.lang.Integer" value="1"/>
<AuxValue name="FormSettings_autoSetComponentName" type="java.lang.Boolean" value="false"/>
<AuxValue name="FormSettings_generateFQN" type="java.lang.Boolean" value="true"/>
<AuxValue name="FormSettings_generateMnemonicsCode" type="java.lang.Boolean" value="true"/>
<AuxValue name="FormSettings_i18nAutoMode" type="java.lang.Boolean" value="true"/>
<AuxValue name="FormSettings_layoutCodeTarget" type="java.lang.Integer" value="1"/>
<AuxValue name="FormSettings_listenerGenerationStyle" type="java.lang.Integer" value="0"/>
<AuxValue name="FormSettings_variablesLocal" type="java.lang.Boolean" value="false"/>
<AuxValue name="FormSettings_variablesModifier" type="java.lang.Integer" value="2"/>
</AuxValues>
<Layout>
<DimensionLayout dim="0">
<Group type="103" groupAlignment="0" attributes="0">
<Group type="102" attributes="0">
<EmptySpace max="-2" attributes="0"/>
<Group type="103" groupAlignment="0" attributes="0">
<Component id="tagNameTextField" pref="220" max="32767" attributes="0"/>
<Group type="102" alignment="0" attributes="0">
<EmptySpace min="0" pref="0" max="32767" attributes="0"/>
<Component id="okButton" min="-2" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Component id="cancelButton" min="-2" max="-2" attributes="0"/>
</Group>
<Component id="newTagNameLabel" alignment="0" max="32767" attributes="0"/>
</Group>
<EmptySpace max="-2" attributes="0"/>
</Group>
</Group>
</DimensionLayout>
<DimensionLayout dim="1">
<Group type="103" groupAlignment="0" attributes="0">
<Group type="102" alignment="0" attributes="0">
<EmptySpace max="-2" attributes="0"/>
<Component id="newTagNameLabel" min="-2" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Component id="tagNameTextField" min="-2" max="-2" attributes="0"/>
<EmptySpace pref="50" max="32767" attributes="0"/>
</Group>
<Group type="102" alignment="1" attributes="0">
<EmptySpace max="32767" attributes="0"/>
<Group type="103" groupAlignment="3" attributes="0">
<Component id="cancelButton" alignment="3" min="-2" max="-2" attributes="0"/>
<Component id="okButton" alignment="3" min="-2" max="-2" attributes="0"/>
</Group>
<EmptySpace max="-2" attributes="0"/>
</Group>
</Group>
</DimensionLayout>
</Layout>
<SubComponents>
<Component class="javax.swing.JLabel" name="newTagNameLabel">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/casemodule/services/Bundle.properties" key="NewTagNameDialog.newTagNameLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
</Properties>
</Component>
<Component class="javax.swing.JTextField" name="tagNameTextField">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/casemodule/services/Bundle.properties" key="NewTagNameDialog.tagNameTextField.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
</Properties>
</Component>
<Component class="javax.swing.JButton" name="cancelButton">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/casemodule/services/Bundle.properties" key="NewTagNameDialog.cancelButton.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
</Properties>
<Events>
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="cancelButtonActionPerformed"/>
</Events>
</Component>
<Component class="javax.swing.JButton" name="okButton">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/casemodule/services/Bundle.properties" key="NewTagNameDialog.okButton.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
</Properties>
<Events>
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="okButtonActionPerformed"/>
</Events>
</Component>
</SubComponents>
</Form>

View File

@ -0,0 +1,247 @@
/*
* Autopsy Forensic Browser
*
* Copyright 2011-2016 Basis Technology Corp.
* Contact: carrier <at> sleuthkit <dot> org
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.sleuthkit.autopsy.casemodule.services;
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.Toolkit;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.event.DocumentEvent;
import javax.swing.event.DocumentListener;
import org.openide.util.NbBundle;
final class NewTagNameDialog extends javax.swing.JDialog {
private static final long serialVersionUID = 1L;
private String userTagDisplayName;
private BUTTON_PRESSED result;
enum BUTTON_PRESSED {
OK, CANCEL;
}
/**
* Creates a new NewUserTagNameDialog dialog.
*/
NewTagNameDialog() {
super(new JFrame(NbBundle.getMessage(NewTagNameDialog.class, "NewUserTagNameDialog.title.text")),
NbBundle.getMessage(NewTagNameDialog.class, "NewUserTagNameDialog.title.text"), true);
initComponents();
this.display();
}
/**
* Sets display settings for the dialog and adds appropriate listeners.
*/
private void display() {
setLayout(new BorderLayout());
/*
* Center the dialog
*/
Dimension screenDimension = Toolkit.getDefaultToolkit().getScreenSize();
int width = this.getSize().width;
int height = this.getSize().height;
setLocation((screenDimension.width - width) / 2, (screenDimension.height - height) / 2);
/*
* Add a handler for when the dialog window is closed directly.
*/
this.addWindowListener(new WindowAdapter() {
@Override
public void windowClosing(WindowEvent e) {
doButtonAction(false);
}
});
/*
* Add a listener to enable the OK button when the text field changes.
*/
tagNameTextField.getDocument().addDocumentListener(new DocumentListener() {
@Override
public void changedUpdate(DocumentEvent e) {
fire();
}
@Override
public void removeUpdate(DocumentEvent e) {
fire();
}
@Override
public void insertUpdate(DocumentEvent e) {
fire();
}
private void fire() {
enableOkButton();
}
});
enableOkButton();
/*
* Used to show the dialog.
*/
setResizable(false);
setVisible(true);
}
/**
* Called when a button is pressed or when the dialog is closed.
* @param okPressed whether the OK button was pressed.
*/
private void doButtonAction(boolean okPressed) {
if (okPressed) {
String newTagDisplayName = tagNameTextField.getText().trim();
if (newTagDisplayName.isEmpty()) {
JOptionPane.showMessageDialog(null,
NbBundle.getMessage(NewTagNameDialog.class, "NewUserTagNameDialog.JOptionPane.tagNameEmpty.message"),
NbBundle.getMessage(NewTagNameDialog.class, "NewUserTagNameDialog.JOptionPane.tagNameEmpty.title"),
JOptionPane.ERROR_MESSAGE);
return;
}
if (TagsManager.containsIllegalCharacters(newTagDisplayName)) {
JOptionPane.showMessageDialog(null,
NbBundle.getMessage(NewTagNameDialog.class, "NewUserTagNameDialog.JOptionPane.tagNameIllegalCharacters.message"),
NbBundle.getMessage(NewTagNameDialog.class, "NewUserTagNameDialog.JOptionPane.tagNameIllegalCharacters.title"),
JOptionPane.ERROR_MESSAGE);
return;
}
userTagDisplayName = newTagDisplayName;
result = BUTTON_PRESSED.OK;
} else {
result = BUTTON_PRESSED.CANCEL;
}
setVisible(false);
}
/**
* Returns the tag name entered by the user.
*
* @return a new user tag name
*/
String getTagName() {
return userTagDisplayName;
}
/**
* Returns information about which button was pressed.
*
* @return BUTTON_PRESSED (OK, CANCEL)
*/
BUTTON_PRESSED getResult() {
return result;
}
/**
* Enable the OK button if the tag name text field is not empty.
* Sets the enter button as default, so user can press enter to activate
* an okButton press and add the tag name.
*/
private void enableOkButton() {
okButton.setEnabled(!tagNameTextField.getText().isEmpty());
getRootPane().setDefaultButton(okButton);
}
/**
* This method is called from within the constructor to initialize the form.
* WARNING: Do NOT modify this code. The content of this method is always
* regenerated by the Form Editor.
*/
@SuppressWarnings("unchecked")
// <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
private void initComponents() {
newTagNameLabel = new javax.swing.JLabel();
tagNameTextField = new javax.swing.JTextField();
cancelButton = new javax.swing.JButton();
okButton = new javax.swing.JButton();
setDefaultCloseOperation(javax.swing.WindowConstants.DISPOSE_ON_CLOSE);
org.openide.awt.Mnemonics.setLocalizedText(newTagNameLabel, org.openide.util.NbBundle.getMessage(NewTagNameDialog.class, "NewTagNameDialog.newTagNameLabel.text")); // NOI18N
tagNameTextField.setText(org.openide.util.NbBundle.getMessage(NewTagNameDialog.class, "NewTagNameDialog.tagNameTextField.text")); // NOI18N
org.openide.awt.Mnemonics.setLocalizedText(cancelButton, org.openide.util.NbBundle.getMessage(NewTagNameDialog.class, "NewTagNameDialog.cancelButton.text")); // NOI18N
cancelButton.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
cancelButtonActionPerformed(evt);
}
});
org.openide.awt.Mnemonics.setLocalizedText(okButton, org.openide.util.NbBundle.getMessage(NewTagNameDialog.class, "NewTagNameDialog.okButton.text")); // NOI18N
okButton.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
okButtonActionPerformed(evt);
}
});
javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
getContentPane().setLayout(layout);
layout.setHorizontalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup()
.addContainerGap()
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(tagNameTextField, javax.swing.GroupLayout.DEFAULT_SIZE, 220, Short.MAX_VALUE)
.addGroup(layout.createSequentialGroup()
.addGap(0, 0, Short.MAX_VALUE)
.addComponent(okButton)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(cancelButton))
.addComponent(newTagNameLabel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
.addContainerGap())
);
layout.setVerticalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup()
.addContainerGap()
.addComponent(newTagNameLabel)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(tagNameTextField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addContainerGap(50, Short.MAX_VALUE))
.addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
.addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
.addComponent(cancelButton)
.addComponent(okButton))
.addContainerGap())
);
pack();
}// </editor-fold>//GEN-END:initComponents
private void okButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_okButtonActionPerformed
doButtonAction(true);
}//GEN-LAST:event_okButtonActionPerformed
private void cancelButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_cancelButtonActionPerformed
doButtonAction(false);
}//GEN-LAST:event_cancelButtonActionPerformed
// Variables declaration - do not modify//GEN-BEGIN:variables
private javax.swing.JButton cancelButton;
private javax.swing.JLabel newTagNameLabel;
private javax.swing.JButton okButton;
private javax.swing.JTextField tagNameTextField;
// End of variables declaration//GEN-END:variables
}

View File

@ -0,0 +1,180 @@
/*
* Autopsy Forensic Browser
*
* Copyright 2011-2016 Basis Technology Corp.
* Contact: carrier <at> sleuthkit <dot> org
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.sleuthkit.autopsy.casemodule.services;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.Objects;
import java.util.Set;
import javax.annotation.concurrent.Immutable;
import org.sleuthkit.autopsy.coreutils.ModuleSettings;
import org.sleuthkit.datamodel.TagName;
/**
* A tag name definition consisting of a display name, description and color.
*/
@Immutable
final class TagNameDefiniton implements Comparable<TagNameDefiniton> {
private static final String TAGS_SETTINGS_NAME = "Tags"; //NON-NLS
private static final String TAG_NAMES_SETTING_KEY = "TagNames"; //NON-NLS
private final String displayName;
private final String description;
private final TagName.HTML_COLOR color;
/**
* Constructs a tag name definition consisting of a display name,
* description and color.
*
* @param displayName The display name for the tag name.
* @param description The description for the tag name.
* @param color The color for the tag name.
*/
TagNameDefiniton(String displayName, String description, TagName.HTML_COLOR color) {
this.displayName = displayName;
this.description = description;
this.color = color;
}
/**
* Gets the display name for the tag name.
*
* @return The display name.
*/
String getDisplayName() {
return displayName;
}
/**
* Gets the description for the tag name.
*
* @return The description.
*/
String getDescription() {
return description;
}
/**
* Gets the color for the tag name.
*
* @return The color.
*/
TagName.HTML_COLOR getColor() {
return color;
}
/**
* Compares this tag name definition with the specified tag name definition
* for order.
*
* @param other The tag name definition to which to compare this tag name
* definition.
*
* @return Negative integer, zero, or a positive integer to indicate that
* this tag name definition is less than, equal to, or greater than
* the specified tag name definition.
*/
@Override
public int compareTo(TagNameDefiniton other) {
return this.getDisplayName().toLowerCase().compareTo(other.getDisplayName().toLowerCase());
}
/**
* Returns a hash code value for this tag name definition.
*
* @return The has code.
*/
@Override
public int hashCode() {
int hash = 7;
hash = 83 * hash + Objects.hashCode(this.displayName);
return hash;
}
/**
* Indicates whether some other object is "equal to" this tag name
* definition.
*
* @param obj The object to test for equality.
*
* @return True or false.
*/
@Override
public boolean equals(Object obj) {
if (!(obj instanceof TagNameDefiniton)) {
return false;
}
TagNameDefiniton thatTagName = (TagNameDefiniton) obj;
return this.getDisplayName().equals(thatTagName.getDisplayName());
}
/**
* A string representation of this tag name definition.
*
* @return The display name of the tag type.
*/
@Override
public String toString() {
return displayName;
}
/**
* @return A string representation of the tag name definition in the format
* that is used by the tags settings file.
*/
private String toSettingsFormat() {
return displayName + "," + description + "," + color.name();
}
/**
* Gets tag name definitions from the tag settings file.
*
* @return A set of tag name definition objects.
*/
static synchronized Set<TagNameDefiniton> getTagNameDefinitions() {
Set<TagNameDefiniton> tagNames = new HashSet<>();
String setting = ModuleSettings.getConfigSetting(TAGS_SETTINGS_NAME, TAG_NAMES_SETTING_KEY);
if (null != setting && !setting.isEmpty()) {
List<String> tagNameTuples = Arrays.asList(setting.split(";"));
for (String tagNameTuple : tagNameTuples) {
String[] tagNameAttributes = tagNameTuple.split(",");
tagNames.add(new TagNameDefiniton(tagNameAttributes[0], tagNameAttributes[1], TagName.HTML_COLOR.valueOf(tagNameAttributes[2])));
}
}
return tagNames;
}
/**
* Sets the tag name definitions in the tag settings file.
*
* @param tagNames A set of tag name definition objects.
*/
static synchronized void setTagNameDefinitions(Set<TagNameDefiniton> tagNames) {
StringBuilder setting = new StringBuilder();
for (TagNameDefiniton tagName : tagNames) {
if (setting.length() != 0) {
setting.append(";");
}
setting.append(tagName.toSettingsFormat());
}
ModuleSettings.setConfigSetting(TAGS_SETTINGS_NAME, TAG_NAMES_SETTING_KEY, setting.toString());
}
}

View File

@ -0,0 +1,204 @@
<?xml version="1.0" encoding="UTF-8" ?>
<Form version="1.5" maxVersion="1.9" type="org.netbeans.modules.form.forminfo.JPanelFormInfo">
<AuxValues>
<AuxValue name="FormSettings_autoResourcing" type="java.lang.Integer" value="1"/>
<AuxValue name="FormSettings_autoSetComponentName" type="java.lang.Boolean" value="false"/>
<AuxValue name="FormSettings_generateFQN" type="java.lang.Boolean" value="true"/>
<AuxValue name="FormSettings_generateMnemonicsCode" type="java.lang.Boolean" value="true"/>
<AuxValue name="FormSettings_i18nAutoMode" type="java.lang.Boolean" value="true"/>
<AuxValue name="FormSettings_layoutCodeTarget" type="java.lang.Integer" value="1"/>
<AuxValue name="FormSettings_listenerGenerationStyle" type="java.lang.Integer" value="0"/>
<AuxValue name="FormSettings_variablesLocal" type="java.lang.Boolean" value="false"/>
<AuxValue name="FormSettings_variablesModifier" type="java.lang.Integer" value="2"/>
</AuxValues>
<Layout>
<DimensionLayout dim="0">
<Group type="103" groupAlignment="0" attributes="0">
<Component id="jPanel1" alignment="0" pref="778" max="32767" attributes="0"/>
</Group>
</DimensionLayout>
<DimensionLayout dim="1">
<Group type="103" groupAlignment="0" attributes="0">
<Group type="102" alignment="0" attributes="0">
<Component id="jPanel1" min="-2" max="-2" attributes="0"/>
<EmptySpace min="0" pref="0" max="32767" attributes="0"/>
</Group>
</Group>
</DimensionLayout>
</Layout>
<SubComponents>
<Container class="javax.swing.JPanel" name="jPanel1">
<Properties>
<Property name="preferredSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[750, 500]"/>
</Property>
</Properties>
<Layout>
<DimensionLayout dim="0">
<Group type="103" groupAlignment="0" attributes="0">
<Group type="102" alignment="1" attributes="0">
<EmptySpace max="-2" attributes="0"/>
<Group type="103" groupAlignment="1" attributes="0">
<Component id="jSplitPane1" max="32767" attributes="0"/>
<Component id="panelDescriptionLabel" max="32767" attributes="0"/>
</Group>
<EmptySpace max="-2" attributes="0"/>
</Group>
</Group>
</DimensionLayout>
<DimensionLayout dim="1">
<Group type="103" groupAlignment="0" attributes="0">
<Group type="102" alignment="0" attributes="0">
<EmptySpace max="-2" attributes="0"/>
<Component id="panelDescriptionLabel" min="-2" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Component id="jSplitPane1" max="32767" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
</Group>
</Group>
</DimensionLayout>
</Layout>
<SubComponents>
<Component class="javax.swing.JLabel" name="panelDescriptionLabel">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/casemodule/services/Bundle.properties" key="TagOptionsPanel.panelDescriptionLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
</Properties>
</Component>
<Container class="javax.swing.JSplitPane" name="jSplitPane1">
<Properties>
<Property name="dividerLocation" type="int" value="400"/>
<Property name="dividerSize" type="int" value="1"/>
</Properties>
<Layout class="org.netbeans.modules.form.compat2.layouts.support.JSplitPaneSupportLayout"/>
<SubComponents>
<Container class="javax.swing.JPanel" name="modifyTagTypesListPanel">
<Constraints>
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.support.JSplitPaneSupportLayout" value="org.netbeans.modules.form.compat2.layouts.support.JSplitPaneSupportLayout$JSplitPaneConstraintsDescription">
<JSplitPaneConstraints position="left"/>
</Constraint>
</Constraints>
<Layout>
<DimensionLayout dim="0">
<Group type="103" groupAlignment="0" attributes="0">
<Group type="102" alignment="0" attributes="0">
<EmptySpace max="-2" attributes="0"/>
<Group type="103" groupAlignment="0" attributes="0">
<Component id="tagTypesListLabel" alignment="0" max="32767" attributes="0"/>
<Group type="102" alignment="0" attributes="0">
<Component id="newTagNameButton" min="-2" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Component id="deleteTagNameButton" min="-2" max="-2" attributes="0"/>
<EmptySpace min="0" pref="113" max="32767" attributes="0"/>
</Group>
<Component id="jScrollPane1" alignment="0" max="32767" attributes="0"/>
</Group>
<EmptySpace max="-2" attributes="0"/>
</Group>
</Group>
</DimensionLayout>
<DimensionLayout dim="1">
<Group type="103" groupAlignment="0" attributes="0">
<Group type="102" alignment="0" attributes="0">
<EmptySpace max="-2" attributes="0"/>
<Component id="tagTypesListLabel" min="-2" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Component id="jScrollPane1" pref="383" max="32767" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Group type="103" groupAlignment="3" attributes="0">
<Component id="newTagNameButton" alignment="3" min="-2" max="-2" attributes="0"/>
<Component id="deleteTagNameButton" alignment="3" min="-2" max="-2" attributes="0"/>
</Group>
<EmptySpace max="-2" attributes="0"/>
</Group>
</Group>
</DimensionLayout>
</Layout>
<SubComponents>
<Component class="javax.swing.JLabel" name="tagTypesListLabel">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/casemodule/services/Bundle.properties" key="TagOptionsPanel.tagTypesListLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
</Properties>
</Component>
<Container class="javax.swing.JScrollPane" name="jScrollPane1">
<AuxValues>
<AuxValue name="autoScrollPane" type="java.lang.Boolean" value="true"/>
</AuxValues>
<Layout class="org.netbeans.modules.form.compat2.layouts.support.JScrollPaneSupportLayout"/>
<SubComponents>
<Component class="javax.swing.JList" name="tagNamesList">
<Properties>
<Property name="model" type="javax.swing.ListModel" editor="org.netbeans.modules.form.editors2.ListModelEditor">
<StringArray count="0"/>
</Property>
<Property name="selectionMode" type="int" value="0"/>
</Properties>
<AuxValues>
<AuxValue name="JavaCodeGenerator_TypeParameters" type="java.lang.String" value="&lt;org.sleuthkit.autopsy.casemodule.services.TagNameDefiniton&gt;"/>
</AuxValues>
</Component>
</SubComponents>
</Container>
<Component class="javax.swing.JButton" name="newTagNameButton">
<Properties>
<Property name="icon" type="javax.swing.Icon" editor="org.netbeans.modules.form.editors2.IconEditor">
<Image iconType="3" name="/org/sleuthkit/autopsy/images/add-tag.png"/>
</Property>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/casemodule/services/Bundle.properties" key="TagOptionsPanel.newTagNameButton.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
</Properties>
<Events>
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="newTagNameButtonActionPerformed"/>
</Events>
</Component>
<Component class="javax.swing.JButton" name="deleteTagNameButton">
<Properties>
<Property name="icon" type="javax.swing.Icon" editor="org.netbeans.modules.form.editors2.IconEditor">
<Image iconType="3" name="/org/sleuthkit/autopsy/images/delete-tag.png"/>
</Property>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/casemodule/services/Bundle.properties" key="TagOptionsPanel.deleteTagNameButton.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
</Properties>
<Events>
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="deleteTagNameButtonActionPerformed"/>
</Events>
</Component>
</SubComponents>
</Container>
<Container class="javax.swing.JPanel" name="tagTypesAdditionalPanel">
<Constraints>
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.support.JSplitPaneSupportLayout" value="org.netbeans.modules.form.compat2.layouts.support.JSplitPaneSupportLayout$JSplitPaneConstraintsDescription">
<JSplitPaneConstraints position="right"/>
</Constraint>
</Constraints>
<Layout>
<DimensionLayout dim="0">
<Group type="103" groupAlignment="0" attributes="0">
<EmptySpace min="0" pref="356" max="32767" attributes="0"/>
</Group>
</DimensionLayout>
<DimensionLayout dim="1">
<Group type="103" groupAlignment="0" attributes="0">
<EmptySpace min="0" pref="456" max="32767" attributes="0"/>
</Group>
</DimensionLayout>
</Layout>
</Container>
</SubComponents>
</Container>
</SubComponents>
</Container>
</SubComponents>
</Form>

View File

@ -0,0 +1,272 @@
/*
* Autopsy Forensic Browser
*
* Copyright 2011-2016 Basis Technology Corp.
* Contact: carrier <at> sleuthkit <dot> org
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.sleuthkit.autopsy.casemodule.services;
import java.util.Set;
import java.util.TreeSet;
import javax.swing.DefaultListModel;
import javax.swing.JOptionPane;
import javax.swing.event.ListSelectionEvent;
import org.netbeans.spi.options.OptionsPanelController;
import org.openide.util.NbBundle;
import org.sleuthkit.autopsy.corecomponents.OptionsPanel;
import org.sleuthkit.datamodel.TagName;
/**
* A panel to allow the user to create and delete custom tag types.
*/
final class TagOptionsPanel extends javax.swing.JPanel implements OptionsPanel {
private static final long serialVersionUID = 1L;
private static final String DEFAULT_DESCRIPTION = "";
private static final TagName.HTML_COLOR DEFAULT_COLOR = TagName.HTML_COLOR.NONE;
private final DefaultListModel<TagNameDefiniton> tagTypesListModel;
private Set<TagNameDefiniton> tagTypes;
/**
* Creates new form TagsManagerOptionsPanel
*/
TagOptionsPanel() {
tagTypesListModel = new DefaultListModel<>();
tagTypes = new TreeSet<>(TagNameDefiniton.getTagNameDefinitions());
initComponents();
customizeComponents();
}
private void customizeComponents() {
tagNamesList.setModel(tagTypesListModel);
tagNamesList.addListSelectionListener((ListSelectionEvent event) -> {
enableButtons();
});
}
/**
* This method is called from within the constructor to initialize the form.
* WARNING: Do NOT modify this code. The content of this method is always
* regenerated by the Form Editor.
*/
@SuppressWarnings("unchecked")
// <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
private void initComponents() {
jPanel1 = new javax.swing.JPanel();
panelDescriptionLabel = new javax.swing.JLabel();
jSplitPane1 = new javax.swing.JSplitPane();
modifyTagTypesListPanel = new javax.swing.JPanel();
tagTypesListLabel = new javax.swing.JLabel();
jScrollPane1 = new javax.swing.JScrollPane();
tagNamesList = new javax.swing.JList<>();
newTagNameButton = new javax.swing.JButton();
deleteTagNameButton = new javax.swing.JButton();
tagTypesAdditionalPanel = new javax.swing.JPanel();
jPanel1.setPreferredSize(new java.awt.Dimension(750, 500));
org.openide.awt.Mnemonics.setLocalizedText(panelDescriptionLabel, org.openide.util.NbBundle.getMessage(TagOptionsPanel.class, "TagOptionsPanel.panelDescriptionLabel.text")); // NOI18N
jSplitPane1.setDividerLocation(400);
jSplitPane1.setDividerSize(1);
org.openide.awt.Mnemonics.setLocalizedText(tagTypesListLabel, org.openide.util.NbBundle.getMessage(TagOptionsPanel.class, "TagOptionsPanel.tagTypesListLabel.text")); // NOI18N
tagNamesList.setSelectionMode(javax.swing.ListSelectionModel.SINGLE_SELECTION);
jScrollPane1.setViewportView(tagNamesList);
newTagNameButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/org/sleuthkit/autopsy/images/add-tag.png"))); // NOI18N
org.openide.awt.Mnemonics.setLocalizedText(newTagNameButton, org.openide.util.NbBundle.getMessage(TagOptionsPanel.class, "TagOptionsPanel.newTagNameButton.text")); // NOI18N
newTagNameButton.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
newTagNameButtonActionPerformed(evt);
}
});
deleteTagNameButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/org/sleuthkit/autopsy/images/delete-tag.png"))); // NOI18N
org.openide.awt.Mnemonics.setLocalizedText(deleteTagNameButton, org.openide.util.NbBundle.getMessage(TagOptionsPanel.class, "TagOptionsPanel.deleteTagNameButton.text")); // NOI18N
deleteTagNameButton.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
deleteTagNameButtonActionPerformed(evt);
}
});
javax.swing.GroupLayout modifyTagTypesListPanelLayout = new javax.swing.GroupLayout(modifyTagTypesListPanel);
modifyTagTypesListPanel.setLayout(modifyTagTypesListPanelLayout);
modifyTagTypesListPanelLayout.setHorizontalGroup(
modifyTagTypesListPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(modifyTagTypesListPanelLayout.createSequentialGroup()
.addContainerGap()
.addGroup(modifyTagTypesListPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(tagTypesListLabel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addGroup(modifyTagTypesListPanelLayout.createSequentialGroup()
.addComponent(newTagNameButton)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(deleteTagNameButton)
.addGap(0, 113, Short.MAX_VALUE))
.addComponent(jScrollPane1))
.addContainerGap())
);
modifyTagTypesListPanelLayout.setVerticalGroup(
modifyTagTypesListPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(modifyTagTypesListPanelLayout.createSequentialGroup()
.addContainerGap()
.addComponent(tagTypesListLabel)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 383, Short.MAX_VALUE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addGroup(modifyTagTypesListPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
.addComponent(newTagNameButton)
.addComponent(deleteTagNameButton))
.addContainerGap())
);
jSplitPane1.setLeftComponent(modifyTagTypesListPanel);
javax.swing.GroupLayout tagTypesAdditionalPanelLayout = new javax.swing.GroupLayout(tagTypesAdditionalPanel);
tagTypesAdditionalPanel.setLayout(tagTypesAdditionalPanelLayout);
tagTypesAdditionalPanelLayout.setHorizontalGroup(
tagTypesAdditionalPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGap(0, 356, Short.MAX_VALUE)
);
tagTypesAdditionalPanelLayout.setVerticalGroup(
tagTypesAdditionalPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGap(0, 456, Short.MAX_VALUE)
);
jSplitPane1.setRightComponent(tagTypesAdditionalPanel);
javax.swing.GroupLayout jPanel1Layout = new javax.swing.GroupLayout(jPanel1);
jPanel1.setLayout(jPanel1Layout);
jPanel1Layout.setHorizontalGroup(
jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(javax.swing.GroupLayout.Alignment.TRAILING, jPanel1Layout.createSequentialGroup()
.addContainerGap()
.addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING)
.addComponent(jSplitPane1)
.addComponent(panelDescriptionLabel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
.addContainerGap())
);
jPanel1Layout.setVerticalGroup(
jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(jPanel1Layout.createSequentialGroup()
.addContainerGap()
.addComponent(panelDescriptionLabel)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(jSplitPane1)
.addContainerGap())
);
javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
this.setLayout(layout);
layout.setHorizontalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(jPanel1, javax.swing.GroupLayout.DEFAULT_SIZE, 778, Short.MAX_VALUE)
);
layout.setVerticalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup()
.addComponent(jPanel1, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addGap(0, 0, Short.MAX_VALUE))
);
}// </editor-fold>//GEN-END:initComponents
private void newTagNameButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_newTagNameButtonActionPerformed
NewTagNameDialog dialog = new NewTagNameDialog();
NewTagNameDialog.BUTTON_PRESSED result = dialog.getResult();
if (result == NewTagNameDialog.BUTTON_PRESSED.OK) {
String newTagDisplayName = dialog.getTagName();
TagNameDefiniton newTagType = new TagNameDefiniton(newTagDisplayName, DEFAULT_DESCRIPTION, DEFAULT_COLOR);
/*
* If tag name already exists, don't add the tag name.
*/
if (!tagTypes.contains(newTagType)) {
tagTypes.add(newTagType);
updateTagNamesListModel();
tagNamesList.setSelectedValue(newTagType, true);
enableButtons();
firePropertyChange(OptionsPanelController.PROP_CHANGED, null, null);
} else {
JOptionPane.showMessageDialog(null,
NbBundle.getMessage(TagOptionsPanel.class, "TagNamesSettingsPanel.JOptionPane.tagNameAlreadyExists.message"),
NbBundle.getMessage(TagOptionsPanel.class, "TagNamesSettingsPanel.JOptionPane.tagNameAlreadyExists.title"),
JOptionPane.INFORMATION_MESSAGE);
}
}
}//GEN-LAST:event_newTagNameButtonActionPerformed
private void deleteTagNameButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_deleteTagNameButtonActionPerformed
TagNameDefiniton tagName = tagNamesList.getSelectedValue();
tagTypes.remove(tagName);
updateTagNamesListModel();
enableButtons();
firePropertyChange(OptionsPanelController.PROP_CHANGED, null, null);
}//GEN-LAST:event_deleteTagNameButtonActionPerformed
// Variables declaration - do not modify//GEN-BEGIN:variables
private javax.swing.JButton deleteTagNameButton;
private javax.swing.JPanel jPanel1;
private javax.swing.JScrollPane jScrollPane1;
private javax.swing.JSplitPane jSplitPane1;
private javax.swing.JPanel modifyTagTypesListPanel;
private javax.swing.JButton newTagNameButton;
private javax.swing.JLabel panelDescriptionLabel;
private javax.swing.JList<org.sleuthkit.autopsy.casemodule.services.TagNameDefiniton> tagNamesList;
private javax.swing.JPanel tagTypesAdditionalPanel;
private javax.swing.JLabel tagTypesListLabel;
// End of variables declaration//GEN-END:variables
/**
* Updates the tag names model for the tag names list component.
*/
private void updateTagNamesListModel() {
tagTypesListModel.clear();
for (TagNameDefiniton tagName : tagTypes) {
tagTypesListModel.addElement(tagName);
}
}
/**
* Loads the stored custom tag types.
*/
@Override
public void load() {
tagTypes = new TreeSet<>(TagNameDefiniton.getTagNameDefinitions());
updateTagNamesListModel();
enableButtons();
}
/**
* Stores the custom tag types.
*/
@Override
public void store() {
TagNameDefiniton.setTagNameDefinitions(tagTypes);
}
/**
* Enables the button components based on the state of the tag types list
* component.
*/
private void enableButtons() {
/*
* Only enable the delete button when there is a tag type selected in
* the tag types JList.
*/
deleteTagNameButton.setEnabled(tagNamesList.getSelectedIndex() != -1);
}
}

View File

@ -22,12 +22,14 @@ import java.io.Closeable;
import java.io.IOException; import java.io.IOException;
import java.util.Arrays; import java.util.Arrays;
import java.util.HashMap; import java.util.HashMap;
import java.util.HashSet;
import java.util.List; import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.logging.Level; import java.util.logging.Level;
import org.openide.util.NbBundle; import org.openide.util.NbBundle;
import org.sleuthkit.autopsy.casemodule.Case; import org.sleuthkit.autopsy.casemodule.Case;
import org.sleuthkit.autopsy.coreutils.Logger; import org.sleuthkit.autopsy.coreutils.Logger;
import org.sleuthkit.autopsy.coreutils.ModuleSettings;
import org.sleuthkit.datamodel.BlackboardArtifact; import org.sleuthkit.datamodel.BlackboardArtifact;
import org.sleuthkit.datamodel.BlackboardArtifactTag; import org.sleuthkit.datamodel.BlackboardArtifactTag;
import org.sleuthkit.datamodel.Content; import org.sleuthkit.datamodel.Content;
@ -37,22 +39,19 @@ import org.sleuthkit.datamodel.TagName;
import org.sleuthkit.datamodel.TskCoreException; import org.sleuthkit.datamodel.TskCoreException;
/** /**
* A per case Autopsy service that manages the creation, updating, and deletion * A per case Autopsy service that manages the addition of content and artifact
* of tags applied to content and blackboard artifacts by users. * tags to the case database.
*/ */
public class TagsManager implements Closeable { public class TagsManager implements Closeable {
private static final Logger logger = Logger.getLogger(TagsManager.class.getName()); private static final Logger LOGGER = Logger.getLogger(TagsManager.class.getName());
private static final String TAGS_SETTINGS_NAME = "Tags"; //NON-NLS @NbBundle.Messages("TagsManager.predefTagNames.bookmark.text=Bookmark")
private static final String TAG_NAMES_SETTING_KEY = "TagNames"; //NON-NLS private static final Set<String> STANDARD_TAG_DISPLAY_NAMES = new HashSet<>(Arrays.asList(Bundle.TagsManager_predefTagNames_bookmark_text()));
private SleuthkitCase caseDb; private final SleuthkitCase caseDb;
private final HashMap<String, TagName> uniqueTagNames = new HashMap<>();
private boolean tagNamesLoaded = false;
/** /**
* Constructs a per case Autopsy service that manages the creation, * Constructs a per case Autopsy service that manages the addition of
* updating, and deletion of tags applied to content and blackboard * content and artifact tags to the case database.
* artifacts by users.
* *
* @param caseDb The case database. * @param caseDb The case database.
*/ */
@ -61,145 +60,152 @@ public class TagsManager implements Closeable {
} }
/** /**
* Gets a list of all tag names currently available for tagging content or * Gets a list of all tag names currently in the case database.
* artifacts.
* *
* @return A list, possibly empty, of TagName data transfer objects (DTOs). * @return A list, possibly empty, of TagName objects.
* *
* @throws TskCoreException If there is an error reading from the case * @throws TskCoreException If there is an error querying the case database.
* database.
*/ */
public synchronized List<TagName> getAllTagNames() throws TskCoreException { public List<TagName> getAllTagNames() throws TskCoreException {
if (null == caseDb) {
throw new TskCoreException("Tags manager has been closed");
}
lazyLoadExistingTagNames();
return caseDb.getAllTagNames(); return caseDb.getAllTagNames();
} }
/** /**
* Gets a list of all tag names currently in use for tagging content or * Gets a list of all tag names currently in use in the case database for
* artifacts. * tagging content or artifacts.
* *
* @return A list, possibly empty, of TagName data transfer objects (DTOs). * @return A list, possibly empty, of TagName objects.
* *
* @throws TskCoreException If there is an error reading from the case * @throws TskCoreException If there is an error querying the case database.
* database.
*/ */
public synchronized List<TagName> getTagNamesInUse() throws TskCoreException { public List<TagName> getTagNamesInUse() throws TskCoreException {
if (null == caseDb) {
throw new TskCoreException("Tags manager has been closed");
}
lazyLoadExistingTagNames();
return caseDb.getTagNamesInUse(); return caseDb.getTagNamesInUse();
} }
/** /**
* Checks whether a tag name with a given display name exists. * Gets a map of tag display names to tag name entries in the case database.
* It has keys for the display names of the standard tag types, the current
* user's custom tag types, and the tags in the case database. The value for
* a given key will be null if the corresponding tag type is defined, but a
* tag name entry has not yet added to the case database. In that case,
* addTagName may be called to add the tag name entry.
* *
* @param tagDisplayName The display name to check. * @return A map of tag display names to possibly null TagName object
* references.
* *
* @return True or false. * @throws TskCoreException if there is an error querying the case database.
*/ */
public synchronized boolean tagNameExists(String tagDisplayName) { public synchronized Map<String, TagName> getDisplayNamesToTagNamesMap() throws TskCoreException {
lazyLoadExistingTagNames(); /**
return uniqueTagNames.containsKey(tagDisplayName); * Order is important here. The keys (display names) for the standard
* tag types and current user's custom tag types are added to the map
* first, with null TagName values. If tag name entries exist for those
* keys, loading of the tag names from the database supplies the missing
* values.
*
* Note that creating the map on demand increases the probability that
* the display names of newly added custom tag types and the display
* names of tags added to a multi-user case by other users appear in the
* map.
*/
Map<String, TagName> tagNames = new HashMap<>();
tagNames.put(NbBundle.getMessage(this.getClass(), "TagsManager.predefTagNames.bookmark.text"), null);
Set<TagNameDefiniton> customTypes = TagNameDefiniton.getTagNameDefinitions();
for (TagNameDefiniton tagType : customTypes) {
tagNames.put(tagType.getDisplayName(), null);
}
for (TagName tagName : caseDb.getAllTagNames()) {
tagNames.put(tagName.getDisplayName(), tagName);
}
return new HashMap<>(tagNames);
} }
/** /**
* Adds a new tag name to the current case and to the tags settings. * Adds a tag name entry to the case database and adds a corresponding tag
* type to the current user's custom tag types.
* *
* @param displayName The display name for the new tag name. * @param displayName The display name for the new tag type.
* *
* @return A TagName data transfer object (DTO) representing the new tag * @return A TagName representing the tag name database entry that can be
* name. * used to add instances of the tag type to the case database.
* *
* @throws TagNameAlreadyExistsException If the tag name would be a * @throws TagNameAlreadyExistsException If the tag name already exists in
* duplicate. * the case database.
* @throws TskCoreException If there is an error adding the tag * @throws TskCoreException If there is an error adding the tag
* to the case database. * name to the case database.
*/ */
public TagName addTagName(String displayName) throws TagNameAlreadyExistsException, TskCoreException { public synchronized TagName addTagName(String displayName) throws TagNameAlreadyExistsException, TskCoreException {
if (null == caseDb) {
throw new TskCoreException("Tags manager has been closed");
}
return addTagName(displayName, "", TagName.HTML_COLOR.NONE); return addTagName(displayName, "", TagName.HTML_COLOR.NONE);
} }
/** /**
* Adds a new tag name to the current case and to the tags settings. * Adds a tag name entry to the case database and adds a corresponding tag
* type to the current user's custom tag types.
* *
* @param displayName The display name for the new tag name. * @param displayName The display name for the new tag type.
* @param description The description for the new tag name. * @param description The description for the new tag type.
* *
* @return A TagName data transfer object (DTO) representing the new tag * @return A TagName object that can be used to add instances of the tag
* name. * type to the case database.
* *
* @throws TagNameAlreadyExistsException If the tag name would be a * @throws TagNameAlreadyExistsException If the tag name already exists in
* duplicate. * the case database.
* @throws TskCoreException If there is an error adding the tag * @throws TskCoreException If there is an error adding the tag
* to the case database. * name to the case database.
*/ */
public TagName addTagName(String displayName, String description) throws TagNameAlreadyExistsException, TskCoreException { public synchronized TagName addTagName(String displayName, String description) throws TagNameAlreadyExistsException, TskCoreException {
if (null == caseDb) {
throw new TskCoreException("Tags manager has been closed");
}
return addTagName(displayName, description, TagName.HTML_COLOR.NONE); return addTagName(displayName, description, TagName.HTML_COLOR.NONE);
} }
/** /**
* Adds a new tag name to the current case and to the tags settings. * Adds a tag name entry to the case database and adds a corresponding tag
* type to the current user's custom tag types.
* *
* @param displayName The display name for the new tag name. * @param displayName The display name for the new tag type.
* @param description The description for the new tag name. * @param description The description for the new tag type.
* @param color The HTML color to associate with the new tag name. * @param color The color to associate with the new tag type.
* *
* @return A TagName data transfer object (DTO) representing the new tag * @return A TagName object that can be used to add instances of the tag
* name. * type to the case database.
* *
* @throws TagNameAlreadyExistsException If the tag name would be a * @throws TagNameAlreadyExistsException If the tag name already exists.
* duplicate.
* @throws TskCoreException If there is an error adding the tag * @throws TskCoreException If there is an error adding the tag
* to the case database. * name to the case database.
*/ */
public synchronized TagName addTagName(String displayName, String description, TagName.HTML_COLOR color) throws TagNameAlreadyExistsException, TskCoreException { public synchronized TagName addTagName(String displayName, String description, TagName.HTML_COLOR color) throws TagNameAlreadyExistsException, TskCoreException {
if (null == caseDb) { try {
throw new TskCoreException("Tags manager has been closed"); TagName tagName = caseDb.addTagName(displayName, description, color);
if (!STANDARD_TAG_DISPLAY_NAMES.contains(displayName)) {
Set<TagNameDefiniton> customTypes = TagNameDefiniton.getTagNameDefinitions();
customTypes.add(new TagNameDefiniton(displayName, description, color));
TagNameDefiniton.setTagNameDefinitions(customTypes);
}
return tagName;
} catch (TskCoreException ex) {
List<TagName> existingTagNames = caseDb.getAllTagNames();
for (TagName tagName : existingTagNames) {
if (tagName.getDisplayName().equals(displayName)) {
throw new TagNameAlreadyExistsException();
}
}
throw ex;
} }
lazyLoadExistingTagNames();
if (uniqueTagNames.containsKey(displayName)) {
throw new TagNameAlreadyExistsException();
}
/*
* Add the tag name to the case.
*/
TagName newTagName = caseDb.addTagName(displayName, description, color);
/*
* Add the tag name to the tags settings.
*/
uniqueTagNames.put(newTagName.getDisplayName(), newTagName);
saveTagNamesToTagsSettings();
return newTagName;
} }
/** /**
* Tags a content object. * Tags a content object.
* *
* @param content The content to tag. * @param content The content to tag.
* @param tagName The name to use for the tag. * @param tagName The representation of the desired tag type in the case
* database, which can be obtained by calling getTagNames
* and/or addTagName.
* *
* @return A ContentTag data transfer object (DTO) representing the new tag. * @return A ContentTag object representing the new tag.
* *
* @throws TskCoreException If there is an error adding the tag to the case * @throws TskCoreException If there is an error adding the tag to the case
* database. * database.
*/ */
public ContentTag addContentTag(Content content, TagName tagName) throws TskCoreException { public ContentTag addContentTag(Content content, TagName tagName) throws TskCoreException {
if (null == caseDb) {
throw new TskCoreException("Tags manager has been closed");
}
return addContentTag(content, tagName, "", -1, -1); return addContentTag(content, tagName, "", -1, -1);
} }
@ -207,18 +213,17 @@ public class TagsManager implements Closeable {
* Tags a content object. * Tags a content object.
* *
* @param content The content to tag. * @param content The content to tag.
* @param tagName The name to use for the tag. * @param tagName The representation of the desired tag type in the case
* database, which can be obtained by calling getTagNames
* and/or addTagName.
* @param comment A comment to store with the tag. * @param comment A comment to store with the tag.
* *
* @return A ContentTag data transfer object (DTO) representing the new tag. * @return A ContentTag object representing the new tag.
* *
* @throws TskCoreException If there is an error adding the tag to the case * @throws TskCoreException If there is an error adding the tag to the case
* database. * database.
*/ */
public ContentTag addContentTag(Content content, TagName tagName, String comment) throws TskCoreException { public ContentTag addContentTag(Content content, TagName tagName, String comment) throws TskCoreException {
if (null == caseDb) {
throw new TskCoreException("Tags manager has been closed");
}
return addContentTag(content, tagName, comment, -1, -1); return addContentTag(content, tagName, comment, -1, -1);
} }
@ -226,56 +231,25 @@ public class TagsManager implements Closeable {
* Tags a content object or a section of a content object. * Tags a content object or a section of a content object.
* *
* @param content The content to tag. * @param content The content to tag.
* @param tagName The name to use for the tag. * @param tagName The representation of the desired tag type in the
* case database, which can be obtained by calling
* getTagNames and/or addTagName.
* @param comment A comment to store with the tag. * @param comment A comment to store with the tag.
* @param beginByteOffset Designates the beginning of a tagged section. * @param beginByteOffset Designates the beginning of a tagged section.
* @param endByteOffset Designates the end of a tagged section. * @param endByteOffset Designates the end of a tagged section.
* *
* @return A ContentTag data transfer object (DTO) representing the new tag. * @return A ContentTag object representing the new tag.
* *
* @throws IllegalArgumentException If a requested byte offset is out of * @throws TskCoreException If there is an error adding the tag to the case
* range. * database.
* @throws TskCoreException If there is an error adding the tag to
* the case database.
*/ */
public ContentTag addContentTag(Content content, TagName tagName, String comment, long beginByteOffset, long endByteOffset) throws IllegalArgumentException, TskCoreException { public ContentTag addContentTag(Content content, TagName tagName, String comment, long beginByteOffset, long endByteOffset) throws TskCoreException {
if (null == caseDb) {
throw new TskCoreException("Tags manager has been closed");
}
ContentTag tag; ContentTag tag;
synchronized (this) { tag = caseDb.addContentTag(content, tagName, comment, beginByteOffset, endByteOffset);
lazyLoadExistingTagNames();
if (null == comment) {
throw new IllegalArgumentException("Passed null comment argument");
}
if (beginByteOffset >= 0 && endByteOffset >= 1) {
if (beginByteOffset > content.getSize() - 1) {
throw new IllegalArgumentException(NbBundle.getMessage(this.getClass(),
"TagsManager.addContentTag.exception.beginByteOffsetOOR.msg",
beginByteOffset, content.getSize() - 1));
}
if (endByteOffset > content.getSize() - 1) {
throw new IllegalArgumentException(
NbBundle.getMessage(this.getClass(), "TagsManager.addContentTag.exception.endByteOffsetOOR.msg",
endByteOffset, content.getSize() - 1));
}
if (endByteOffset < beginByteOffset) {
throw new IllegalArgumentException(
NbBundle.getMessage(this.getClass(), "TagsManager.addContentTag.exception.endLTbegin.msg"));
}
}
tag = caseDb.addContentTag(content, tagName, comment, beginByteOffset, endByteOffset);
}
try { try {
Case.getCurrentCase().notifyContentTagAdded(tag); Case.getCurrentCase().notifyContentTagAdded(tag);
} catch (IllegalStateException ex) { } catch (IllegalStateException ex) {
logger.log(Level.SEVERE, NbBundle.getMessage(TagsManager.class, "TagsManager.addContentTag.noCaseWarning"), ex); LOGGER.log(Level.SEVERE, "Added a tag to a closed case", ex);
} }
return tag; return tag;
} }
@ -289,18 +263,11 @@ public class TagsManager implements Closeable {
* case database. * case database.
*/ */
public void deleteContentTag(ContentTag tag) throws TskCoreException { public void deleteContentTag(ContentTag tag) throws TskCoreException {
if (null == caseDb) { caseDb.deleteContentTag(tag);
throw new TskCoreException("Tags manager has been closed");
}
synchronized (this) {
lazyLoadExistingTagNames();
caseDb.deleteContentTag(tag);
}
try { try {
Case.getCurrentCase().notifyContentTagDeleted(tag); Case.getCurrentCase().notifyContentTagDeleted(tag);
} catch (IllegalStateException ex) { } catch (IllegalStateException ex) {
logger.log(Level.SEVERE, NbBundle.getMessage(TagsManager.class, "TagsManager.deleteContentTag.noCaseWarning"), ex); LOGGER.log(Level.SEVERE, "Deleted a tag from a closed case", ex);
} }
} }
@ -313,17 +280,15 @@ public class TagsManager implements Closeable {
* case database. * case database.
*/ */
public synchronized List<ContentTag> getAllContentTags() throws TskCoreException { public synchronized List<ContentTag> getAllContentTags() throws TskCoreException {
if (null == caseDb) {
throw new TskCoreException("Tags manager has been closed");
}
lazyLoadExistingTagNames();
return caseDb.getAllContentTags(); return caseDb.getAllContentTags();
} }
/** /**
* Gets content tags count by tag name. * Gets content tags count by tag name.
* *
* @param tagName The tag name of interest. * @param tagName The representation of the desired tag type in the case
* database, which can be obtained by calling getTagNames
* and/or addTagName.
* *
* @return A count of the content tags with the specified tag name. * @return A count of the content tags with the specified tag name.
* *
@ -331,29 +296,21 @@ public class TagsManager implements Closeable {
* the case database. * the case database.
*/ */
public synchronized long getContentTagsCountByTagName(TagName tagName) throws TskCoreException { public synchronized long getContentTagsCountByTagName(TagName tagName) throws TskCoreException {
if (null == caseDb) {
throw new TskCoreException("Tags manager has been closed");
}
lazyLoadExistingTagNames();
return caseDb.getContentTagsCountByTagName(tagName); return caseDb.getContentTagsCountByTagName(tagName);
} }
/** /**
* Gets a content tag by tag id. * Gets a content tag by tag id.
* *
* @param tagID The tag id of interest. * @param tagId The tag id of interest.
* *
* @return The content tag with the specified tag id. * @return The content tag with the specified tag id.
* *
* @throws TskCoreException If there is an error getting the tag from the * @throws TskCoreException If there is an error getting the tag from the
* case database. * case database.
*/ */
public synchronized ContentTag getContentTagByTagID(long tagID) throws TskCoreException { public synchronized ContentTag getContentTagByTagID(long tagId) throws TskCoreException {
if (null == caseDb) { return caseDb.getContentTagByID(tagId);
throw new TskCoreException("Tags manager has been closed");
}
lazyLoadExistingTagNames();
return caseDb.getContentTagByID(tagID);
} }
/** /**
@ -368,10 +325,6 @@ public class TagsManager implements Closeable {
* case database. * case database.
*/ */
public synchronized List<ContentTag> getContentTagsByTagName(TagName tagName) throws TskCoreException { public synchronized List<ContentTag> getContentTagsByTagName(TagName tagName) throws TskCoreException {
if (null == caseDb) {
throw new TskCoreException("Tags manager has been closed");
}
lazyLoadExistingTagNames();
return caseDb.getContentTagsByTagName(tagName); return caseDb.getContentTagsByTagName(tagName);
} }
@ -381,172 +334,136 @@ public class TagsManager implements Closeable {
* @param content The content of interest. * @param content The content of interest.
* *
* @return A list, possibly empty, of the tags that have been applied to the * @return A list, possibly empty, of the tags that have been applied to the
* artifact. * content.
* *
* @throws TskCoreException If there is an error getting the tags from the * @throws TskCoreException If there is an error getting the tags from the
* case database. * case database.
*/ */
public synchronized List<ContentTag> getContentTagsByContent(Content content) throws TskCoreException { public synchronized List<ContentTag> getContentTagsByContent(Content content) throws TskCoreException {
if (null == caseDb) {
throw new TskCoreException("Tags manager has been closed");
}
lazyLoadExistingTagNames();
return caseDb.getContentTagsByContent(content); return caseDb.getContentTagsByContent(content);
} }
/** /**
* Tags a blackboard artifact object. * Tags an artifact.
* *
* @param artifact The blackboard artifact to tag. * @param artifact The artifact to tag.
* @param tagName The name to use for the tag. * @param tagName The representation of the desired tag type in the case
* database, which can be obtained by calling getTagNames
* and/or addTagName.
* *
* @return A BlackboardArtifactTag data transfer object (DTO) representing * @return A BlackboardArtifactTag object representing the new tag.
* the new tag.
* *
* @throws TskCoreException If there is an error adding the tag to the case * @throws TskCoreException If there is an error adding the tag to the case
* database. * database.
*/ */
public BlackboardArtifactTag addBlackboardArtifactTag(BlackboardArtifact artifact, TagName tagName) throws TskCoreException { public synchronized BlackboardArtifactTag addBlackboardArtifactTag(BlackboardArtifact artifact, TagName tagName) throws TskCoreException {
if (null == caseDb) {
throw new TskCoreException("Tags manager has been closed");
}
return addBlackboardArtifactTag(artifact, tagName, ""); return addBlackboardArtifactTag(artifact, tagName, "");
} }
/** /**
* Tags a blackboard artifact object. * Tags an artifact.
* *
* @param artifact The blackboard artifact to tag. * @param artifact The artifact to tag.
* @param tagName The name to use for the tag. * @param tagName The representation of the desired tag type in the case
* database, which can be obtained by calling getTagNames
* and/or addTagName.
* @param comment A comment to store with the tag. * @param comment A comment to store with the tag.
* *
* @return A BlackboardArtifactTag data transfer object (DTO) representing * @return A BlackboardArtifactTag object representing the new tag.
* the new tag.
* *
* @throws TskCoreException If there is an error adding the tag to the case * @throws TskCoreException If there is an error adding the tag to the case
* database. * database.
*/ */
public BlackboardArtifactTag addBlackboardArtifactTag(BlackboardArtifact artifact, TagName tagName, String comment) throws TskCoreException { public synchronized BlackboardArtifactTag addBlackboardArtifactTag(BlackboardArtifact artifact, TagName tagName, String comment) throws TskCoreException {
if (null == caseDb) { BlackboardArtifactTag tag = caseDb.addBlackboardArtifactTag(artifact, tagName, comment);
throw new TskCoreException("Tags manager has been closed");
}
BlackboardArtifactTag tag;
synchronized (this) {
lazyLoadExistingTagNames();
if (null == comment) {
throw new IllegalArgumentException("Passed null comment argument");
}
tag = caseDb.addBlackboardArtifactTag(artifact, tagName, comment);
}
try { try {
Case.getCurrentCase().notifyBlackBoardArtifactTagAdded(tag); Case.getCurrentCase().notifyBlackBoardArtifactTagAdded(tag);
} catch (IllegalStateException ex) { } catch (IllegalStateException ex) {
logger.log(Level.SEVERE, NbBundle.getMessage(TagsManager.class, "TagsManager.addBlackboardArtifactTag.noCaseWarning"), ex); LOGGER.log(Level.SEVERE, "Added a tag to a closed case", ex);
} }
return tag; return tag;
} }
/** /**
* Deletes a blackboard artifact tag. * Deletes an artifact tag.
* *
* @param tag The tag to delete. * @param tag The tag to delete.
* *
* @throws TskCoreException If there is an error deleting the tag from the * @throws TskCoreException If there is an error deleting the tag from the
* case database. * case database.
*/ */
public void deleteBlackboardArtifactTag(BlackboardArtifactTag tag) throws TskCoreException { public synchronized void deleteBlackboardArtifactTag(BlackboardArtifactTag tag) throws TskCoreException {
if (null == caseDb) { caseDb.deleteBlackboardArtifactTag(tag);
throw new TskCoreException("Tags manager has been closed");
}
synchronized (this) {
lazyLoadExistingTagNames();
caseDb.deleteBlackboardArtifactTag(tag);
}
try { try {
Case.getCurrentCase().notifyBlackBoardArtifactTagDeleted(tag); Case.getCurrentCase().notifyBlackBoardArtifactTagDeleted(tag);
} catch (IllegalStateException ex) { } catch (IllegalStateException ex) {
logger.log(Level.WARNING, NbBundle.getMessage(TagsManager.class, "TagsManager.deleteBlackboardArtifactTag.noCaseWarning"), ex); LOGGER.log(Level.SEVERE, "Deleted a tag from a closed case", ex);
} }
} }
/** /**
* Gets all blackboard artifact tags for the current case. * Gets all artifact tags for the current case.
* *
* @return A list, possibly empty, of blackboard artifact tags. * @return A list, possibly empty, of artifact tags.
* *
* @throws TskCoreException If there is an error getting the tags from the * @throws TskCoreException If there is an error getting the tags from the
* case database. * case database.
*/ */
public synchronized List<BlackboardArtifactTag> getAllBlackboardArtifactTags() throws TskCoreException { public synchronized List<BlackboardArtifactTag> getAllBlackboardArtifactTags() throws TskCoreException {
if (null == caseDb) {
throw new TskCoreException("Tags manager has been closed");
}
lazyLoadExistingTagNames();
return caseDb.getAllBlackboardArtifactTags(); return caseDb.getAllBlackboardArtifactTags();
} }
/** /**
* Gets blackboard artifact tags count by tag name. * Gets an artifact tags count by tag name.
* *
* @param tagName The tag name of interest. * @param tagName The representation of the desired tag type in the case
* database, which can be obtained by calling getTagNames
* and/or addTagName.
* *
* @return A count of the blackboard artifact tags with the specified tag * @return A count of the artifact tags with the specified tag name.
* name.
* *
* @throws TskCoreException If there is an error getting the tags count from * @throws TskCoreException If there is an error getting the tags count from
* the case database. * the case database.
*/ */
public synchronized long getBlackboardArtifactTagsCountByTagName(TagName tagName) throws TskCoreException { public synchronized long getBlackboardArtifactTagsCountByTagName(TagName tagName) throws TskCoreException {
if (null == caseDb) {
throw new TskCoreException("Tags manager has been closed");
}
lazyLoadExistingTagNames();
return caseDb.getBlackboardArtifactTagsCountByTagName(tagName); return caseDb.getBlackboardArtifactTagsCountByTagName(tagName);
} }
/** /**
* Gets a blackboard artifact tag by tag id. * Gets an artifact tag by tag id.
* *
* @param tagID The tag id of interest. * @param tagId The tag id of interest.
* *
* @return the blackboard artifact tag with the specified tag id. * @return The artifact tag with the specified tag id.
* *
* @throws TskCoreException If there is an error getting the tag from the * @throws TskCoreException If there is an error getting the tag from the
* case database. * case database.
*/ */
public synchronized BlackboardArtifactTag getBlackboardArtifactTagByTagID(long tagID) throws TskCoreException { public synchronized BlackboardArtifactTag getBlackboardArtifactTagByTagID(long tagId) throws TskCoreException {
if (null == caseDb) { return caseDb.getBlackboardArtifactTagByID(tagId);
throw new TskCoreException("Tags manager has been closed");
}
lazyLoadExistingTagNames();
return caseDb.getBlackboardArtifactTagByID(tagID);
} }
/** /**
* Gets blackboard artifact tags by tag name. * Gets artifact tags by tag name.
* *
* @param tagName The tag name of interest. * @param tagName The representation of the desired tag type in the case
* database, which can be obtained by calling getTagNames
* and/or addTagName.
* *
* @return A list, possibly empty, of the blackboard artifact tags with the * @return A list, possibly empty, of the artifact tags with the specified
* specified tag name. * tag name.
* *
* @throws TskCoreException If there is an error getting the tags from the * @throws TskCoreException If there is an error getting the tags from the
* case database. * case database.
*/ */
public synchronized List<BlackboardArtifactTag> getBlackboardArtifactTagsByTagName(TagName tagName) throws TskCoreException { public synchronized List<BlackboardArtifactTag> getBlackboardArtifactTagsByTagName(TagName tagName) throws TskCoreException {
if (null == caseDb) {
throw new TskCoreException("Tags manager has been closed");
}
lazyLoadExistingTagNames();
return caseDb.getBlackboardArtifactTagsByTagName(tagName); return caseDb.getBlackboardArtifactTagsByTagName(tagName);
} }
/** /**
* Gets blackboard artifact tags for a particular blackboard artifact. * Gets artifact tags for a particular artifact.
* *
* @param artifact The blackboard artifact of interest. * @param artifact The artifact of interest.
* *
* @return A list, possibly empty, of the tags that have been applied to the * @return A list, possibly empty, of the tags that have been applied to the
* artifact. * artifact.
@ -555,115 +472,29 @@ public class TagsManager implements Closeable {
* case database. * case database.
*/ */
public synchronized List<BlackboardArtifactTag> getBlackboardArtifactTagsByArtifact(BlackboardArtifact artifact) throws TskCoreException { public synchronized List<BlackboardArtifactTag> getBlackboardArtifactTagsByArtifact(BlackboardArtifact artifact) throws TskCoreException {
if (null == caseDb) {
throw new TskCoreException("Tags manager has been closed");
}
lazyLoadExistingTagNames();
return caseDb.getBlackboardArtifactTagsByArtifact(artifact); return caseDb.getBlackboardArtifactTagsByArtifact(artifact);
} }
/** /**
* Closes the tags manager, saving the avaialble tag names to secondary * Returns true if the tag display name contains an illegal character. Used
* storage. * after a tag display name is retrieved from user input.
* *
* @throws IOException If there is a problem closing the tags manager. * @param content Display name of the tag being added.
* @deprecated Tags manager clients should not close the tags manager. *
* @return boolean indicating whether the name has an invalid character.
*/ */
@Override public static boolean containsIllegalCharacters(String content) {
@Deprecated return (content.contains("\\")
public synchronized void close() throws IOException { || content.contains(":")
saveTagNamesToTagsSettings(); || content.contains("*")
caseDb = null; || content.contains("?")
} || content.contains("\"")
|| content.contains("<")
|| content.contains(">")
|| content.contains("|")
|| content.contains(",")
|| content.contains(";"));
/**
* Populates the tag names collection and the tag names table in the case
* database with the existing tag names from all sources.
*/
private void lazyLoadExistingTagNames() {
if (!tagNamesLoaded) {
addTagNamesFromCurrentCase();
addTagNamesFromTagsSettings();
addPredefinedTagNames();
saveTagNamesToTagsSettings();
tagNamesLoaded = true;
}
}
/**
* Adds any tag names that are in the case database to the tag names
* collection.
*/
private void addTagNamesFromCurrentCase() {
try {
List<TagName> currentTagNames = caseDb.getAllTagNames();
for (TagName tagName : currentTagNames) {
uniqueTagNames.put(tagName.getDisplayName(), tagName);
}
} catch (TskCoreException ex) {
Logger.getLogger(TagsManager.class.getName()).log(Level.SEVERE, "Failed to get tag types from the current case", ex); //NON-NLS
}
}
/**
* Adds any tag names that are in the properties file to the tag names
* collection and to the case database. The properties file is used to make
* it possible to use tag names across cases.
*/
private void addTagNamesFromTagsSettings() {
String setting = ModuleSettings.getConfigSetting(TAGS_SETTINGS_NAME, TAG_NAMES_SETTING_KEY);
if (null != setting && !setting.isEmpty()) {
// Read the tag name setting and break it into tag name tuples.
List<String> tagNameTuples = Arrays.asList(setting.split(";"));
// Parse each tuple and add the tag names to the current case, one
// at a time to gracefully discard any duplicates or corrupt tuples.
for (String tagNameTuple : tagNameTuples) {
String[] tagNameAttributes = tagNameTuple.split(",");
if (!uniqueTagNames.containsKey(tagNameAttributes[0])) {
try {
TagName tagName = caseDb.addTagName(tagNameAttributes[0], tagNameAttributes[1], TagName.HTML_COLOR.getColorByName(tagNameAttributes[2]));
uniqueTagNames.put(tagName.getDisplayName(), tagName);
} catch (TskCoreException ex) {
Logger.getLogger(TagsManager.class.getName()).log(Level.SEVERE, "Failed to add saved tag name " + tagNameAttributes[0], ex); //NON-NLS
}
}
}
}
}
/**
* Adds the standard tag names to the tag names collection.
*/
private void addPredefinedTagNames() {
if (!uniqueTagNames.containsKey(NbBundle.getMessage(this.getClass(), "TagsManager.predefTagNames.bookmark.text"))) {
try {
TagName tagName = caseDb.addTagName(
NbBundle.getMessage(this.getClass(), "TagsManager.predefTagNames.bookmark.text"), "", TagName.HTML_COLOR.NONE);
uniqueTagNames.put(tagName.getDisplayName(), tagName);
} catch (TskCoreException ex) {
Logger.getLogger(TagsManager.class.getName()).log(Level.SEVERE, "Failed to add standard 'Bookmark' tag name to case database", ex); //NON-NLS
}
}
}
/**
* Saves the tag names to a properties file. The properties file is used to
* make it possible to use tag names across cases.
*/
private void saveTagNamesToTagsSettings() {
if (!uniqueTagNames.isEmpty()) {
StringBuilder setting = new StringBuilder();
for (TagName tagName : uniqueTagNames.values()) {
if (setting.length() != 0) {
setting.append(";");
}
setting.append(tagName.getDisplayName()).append(",");
setting.append(tagName.getDescription()).append(",");
setting.append(tagName.getColor().name());
}
ModuleSettings.setConfigSetting(TAGS_SETTINGS_NAME, TAG_NAMES_SETTING_KEY, setting.toString());
}
} }
/** /**
@ -674,4 +505,36 @@ public class TagsManager implements Closeable {
private static final long serialVersionUID = 1L; private static final long serialVersionUID = 1L;
} }
/**
* Checks whether a tag name with a given display name exists in the case
* database.
*
* @param tagDisplayName The display name.
*
* @return True or false.
*
* @deprecated Not reliable for multi-user cases.
*/
@Deprecated
public synchronized boolean tagNameExists(String tagDisplayName) {
try {
Map<String, TagName> tagNames = getDisplayNamesToTagNamesMap();
return tagNames.containsKey(tagDisplayName) && (tagNames.get(tagDisplayName) != null);
} catch (TskCoreException ex) {
LOGGER.log(Level.SEVERE, "Error querying case database for tag names", ex);
return false;
}
}
/**
* Closes the tags manager.
*
* @throws IOException If there is a problem closing the tags manager.
* @deprecated Tags manager clients should not close the tags manager.
*/
@Override
@Deprecated
public synchronized void close() throws IOException {
}
} }

View File

@ -0,0 +1,128 @@
/*
* Autopsy Forensic Browser
*
* Copyright 2011-2016 Basis Technology Corp.
* Contact: carrier <at> sleuthkit <dot> org
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.sleuthkit.autopsy.casemodule.services;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.beans.PropertyChangeSupport;
import javax.swing.JComponent;
import org.netbeans.spi.options.OptionsPanelController;
import org.openide.util.HelpCtx;
import org.openide.util.Lookup;
@OptionsPanelController.TopLevelRegistration(
categoryName = "#OptionsCategory_Name_TagNamesOptions",
iconBase = "org/sleuthkit/autopsy/casemodule/services/tag-options-panel-icon.png",
keywords = "#OptionsCategory_TagNames",
keywordsCategory = "CustomTagNames",
position = 8
)
public final class TagsOptionsPanelController extends OptionsPanelController {
private TagOptionsPanel panel;
private final PropertyChangeSupport pcs = new PropertyChangeSupport(this);
private boolean changed;
/**
* Component should load its data here.
*/
@Override
public void update() {
getPanel().load();
changed = false;
}
/**
* This method is called when both the Ok and Apply buttons are pressed. It
* applies to any of the panels that have been opened in the process of
* using the options pane.
*/
@Override
public void applyChanges() {
if (changed) {
getPanel().store();
changed = false;
}
}
/**
* This method is called when the Cancel button is pressed. It applies to
* any of the panels that have been opened in the process of using the
* options pane.
*/
@Override
public void cancel() {
}
@Override
public boolean isValid() {
return true;
}
/**
* Used to determine whether any changes have been made to this controller's
* panel.
*
* @return Whether or not a change has been made.
*/
@Override
public boolean isChanged() {
return changed;
}
@Override
public JComponent getComponent(Lookup lkp) {
return getPanel();
}
@Override
public HelpCtx getHelpCtx() {
return null;
}
@Override
public void addPropertyChangeListener(PropertyChangeListener l) {
pcs.addPropertyChangeListener(l);
}
@Override
public void removePropertyChangeListener(PropertyChangeListener l) {
pcs.removePropertyChangeListener(l);
}
private TagOptionsPanel getPanel() {
if (panel == null) {
panel = new TagOptionsPanel();
panel.addPropertyChangeListener((PropertyChangeEvent evt) -> {
if (evt.getPropertyName().equals(OptionsPanelController.PROP_CHANGED)) {
changed();
}
});
}
return panel;
}
void changed() {
if (!changed) {
changed = true;
pcs.firePropertyChange(OptionsPanelController.PROP_CHANGED, false, true);
}
pcs.firePropertyChange(OptionsPanelController.PROP_VALID, null, null);
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

View File

@ -1,7 +1,7 @@
/* /*
* Autopsy Forensic Browser * Autopsy Forensic Browser
* *
* Copyright 2013 Basis Technology Corp. * Copyright 2011-2016 Basis Technology Corp.
* Contact: carrier <at> sleuthkit <dot> org * Contact: carrier <at> sleuthkit <dot> org
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
@ -61,6 +61,7 @@ import org.sleuthkit.datamodel.TskCoreException;
//@ServiceProvider(service = DataResultViewer.class) //@ServiceProvider(service = DataResultViewer.class)
final class DataResultViewerThumbnail extends AbstractDataResultViewer { final class DataResultViewerThumbnail extends AbstractDataResultViewer {
private static final long serialVersionUID = 1L;
private static final Logger logger = Logger.getLogger(DataResultViewerThumbnail.class.getName()); private static final Logger logger = Logger.getLogger(DataResultViewerThumbnail.class.getName());
//flag to keep track if images are being loaded //flag to keep track if images are being loaded
private int curPage; private int curPage;
@ -95,7 +96,7 @@ final class DataResultViewerThumbnail extends AbstractDataResultViewer {
iconView.setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION); iconView.setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION);
em.addPropertyChangeListener(new ExplorerManagerNodeSelectionListener()); em.addPropertyChangeListener(new ExplorerManagerNodeSelectionListener());
thumbnailSizeComboBox.setModel(new javax.swing.DefaultComboBoxModel<String>( thumbnailSizeComboBox.setModel(new javax.swing.DefaultComboBoxModel<>(
new String[] { Bundle.DataResultViewerThumbnail_thumbnailSizeComboBox_small(), new String[] { Bundle.DataResultViewerThumbnail_thumbnailSizeComboBox_small(),
Bundle.DataResultViewerThumbnail_thumbnailSizeComboBox_medium(), Bundle.DataResultViewerThumbnail_thumbnailSizeComboBox_medium(),
Bundle.DataResultViewerThumbnail_thumbnailSizeComboBox_large() })); Bundle.DataResultViewerThumbnail_thumbnailSizeComboBox_large() }));
@ -395,11 +396,8 @@ final class DataResultViewerThumbnail extends AbstractDataResultViewer {
private void switchPage() { private void switchPage() {
EventQueue.invokeLater(new Runnable() { EventQueue.invokeLater(() -> {
@Override setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
public void run() {
setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
}
}); });
//Note the nodes factories are likely creating nodes in EDT anyway, but worker still helps //Note the nodes factories are likely creating nodes in EDT anyway, but worker still helps
@ -437,7 +435,7 @@ final class DataResultViewerThumbnail extends AbstractDataResultViewer {
ex.getMessage()), ex.getMessage()),
NotifyDescriptor.ERROR_MESSAGE); NotifyDescriptor.ERROR_MESSAGE);
DialogDisplayer.getDefault().notify(d); DialogDisplayer.getDefault().notify(d);
logger.log(Level.SEVERE, "Error making thumbnails: " + ex.getMessage()); //NON-NLS logger.log(Level.SEVERE, "Error making thumbnails: {0}", ex.getMessage()); //NON-NLS
} // catch and ignore if we were cancelled } // catch and ignore if we were cancelled
catch (java.util.concurrent.CancellationException ex) { catch (java.util.concurrent.CancellationException ex) {
} }
@ -453,6 +451,7 @@ final class DataResultViewerThumbnail extends AbstractDataResultViewer {
goToPageField.setEnabled(false); goToPageField.setEnabled(false);
pageNumLabel.setText(""); pageNumLabel.setText("");
imagesRangeLabel.setText(""); imagesRangeLabel.setText("");
thumbnailSizeComboBox.setEnabled(false);
} else { } else {
pageNumLabel.setText( pageNumLabel.setText(
NbBundle.getMessage(this.getClass(), "DataResultViewerThumbnail.pageNumbers.curOfTotal", NbBundle.getMessage(this.getClass(), "DataResultViewerThumbnail.pageNumbers.curOfTotal",
@ -464,7 +463,7 @@ final class DataResultViewerThumbnail extends AbstractDataResultViewer {
pageNextButton.setEnabled(!(curPage == totalPages)); pageNextButton.setEnabled(!(curPage == totalPages));
pagePrevButton.setEnabled(!(curPage == 1)); pagePrevButton.setEnabled(!(curPage == 1));
goToPageField.setEnabled(totalPages > 1); goToPageField.setEnabled(totalPages > 1);
thumbnailSizeComboBox.setEnabled(true);
} }
} }

View File

@ -22,6 +22,12 @@ import org.openide.nodes.AbstractNode;
import org.openide.nodes.Children.Keys; import org.openide.nodes.Children.Keys;
import org.openide.nodes.Node; import org.openide.nodes.Node;
import org.openide.util.NbBundle; import org.openide.util.NbBundle;
import org.sleuthkit.autopsy.datamodel._private.AutopsyItemVisitor;
import org.sleuthkit.autopsy.datamodel._private.AutopsyVisitableItem;
import org.sleuthkit.autopsy.datamodel._private.FileTypeExtensionFilters;
import org.sleuthkit.autopsy.datamodel._private.RecentFiles;
import org.sleuthkit.autopsy.datamodel._private.Accounts;
import org.sleuthkit.autopsy.datamodel._private.Accounts.AccountsRootNode;
import org.sleuthkit.datamodel.Content; import org.sleuthkit.datamodel.Content;
import org.sleuthkit.datamodel.DerivedFile; import org.sleuthkit.datamodel.DerivedFile;
import org.sleuthkit.datamodel.Directory; import org.sleuthkit.datamodel.Directory;

File diff suppressed because it is too large Load Diff

View File

@ -27,7 +27,6 @@ import org.openide.util.NbBundle;
import org.sleuthkit.autopsy.coreutils.Logger; import org.sleuthkit.autopsy.coreutils.Logger;
import org.sleuthkit.datamodel.BlackboardArtifact; import org.sleuthkit.datamodel.BlackboardArtifact;
import org.sleuthkit.datamodel.BlackboardAttribute; import org.sleuthkit.datamodel.BlackboardAttribute;
import org.sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE;
import org.sleuthkit.datamodel.Content; import org.sleuthkit.datamodel.Content;
import org.sleuthkit.datamodel.TskCoreException; import org.sleuthkit.datamodel.TskCoreException;
import org.sleuthkit.datamodel.TskException; import org.sleuthkit.datamodel.TskException;
@ -78,48 +77,36 @@ public class ArtifactStringContent implements StringContent {
// value column // value column
buffer.append("<td>"); //NON-NLS buffer.append("<td>"); //NON-NLS
if (attr.getAttributeType().getTypeID() == ATTRIBUTE_TYPE.TSK_DATETIME.getTypeID() switch (attr.getAttributeType().getValueType()) {
|| attr.getAttributeType().getTypeID() == ATTRIBUTE_TYPE.TSK_DATETIME_ACCESSED.getTypeID() case STRING:
|| attr.getAttributeType().getTypeID() == ATTRIBUTE_TYPE.TSK_DATETIME_CREATED.getTypeID() String str = attr.getValueString();
|| attr.getAttributeType().getTypeID() == ATTRIBUTE_TYPE.TSK_DATETIME_MODIFIED.getTypeID() str = str.replaceAll(" ", "&nbsp;"); //NON-NLS
|| attr.getAttributeType().getTypeID() == ATTRIBUTE_TYPE.TSK_DATETIME_RCVD.getTypeID() str = str.replaceAll("<", "&lt;"); //NON-NLS
|| attr.getAttributeType().getTypeID() == ATTRIBUTE_TYPE.TSK_DATETIME_SENT.getTypeID() str = str.replaceAll(">", "&gt;"); //NON-NLS
|| attr.getAttributeType().getTypeID() == ATTRIBUTE_TYPE.TSK_DATETIME_START.getTypeID() str = str.replaceAll("(\r\n|\n)", "<br />"); //NON-NLS
|| attr.getAttributeType().getTypeID() == ATTRIBUTE_TYPE.TSK_DATETIME_END.getTypeID()) { buffer.append(str);
long epoch = attr.getValueLong(); break;
String time = "0000-00-00 00:00:00"; case INTEGER:
if (epoch != 0) { buffer.append(attr.getValueInt());
dateFormatter.setTimeZone(getTimeZone(artifact)); break;
time = dateFormatter.format(new java.util.Date(epoch * 1000)); case LONG:
} buffer.append(attr.getValueLong());
buffer.append(time); break;
} else { case DOUBLE:
switch (attr.getAttributeType().getValueType()) { buffer.append(attr.getValueDouble());
case STRING: break;
String str = attr.getValueString(); case BYTE:
str = str.replaceAll(" ", "&nbsp;"); //NON-NLS buffer.append(Arrays.toString(attr.getValueBytes()));
str = str.replaceAll("<", "&lt;"); //NON-NLS break;
str = str.replaceAll(">", "&gt;"); //NON-NLS case DATETIME:
str = str.replaceAll("(\r\n|\n)", "<br />"); //NON-NLS long epoch = attr.getValueLong();
buffer.append(str); String time = "0000-00-00 00:00:00";
break; if (epoch != 0) {
case INTEGER: dateFormatter.setTimeZone(getTimeZone(artifact));
buffer.append(attr.getValueInt()); time = dateFormatter.format(new java.util.Date(epoch * 1000));
break; }
case LONG: buffer.append(time);
buffer.append(attr.getValueLong()); break;
break;
case DOUBLE:
buffer.append(attr.getValueDouble());
break;
case BYTE:
buffer.append(Arrays.toString(attr.getValueBytes()));
break;
case DATETIME:
buffer.append(attr.getValueLong());
break;
}
} }
if (!"".equals(attr.getContext())) { if (!"".equals(attr.getContext())) {
buffer.append(" ("); buffer.append(" (");

View File

@ -185,13 +185,13 @@ public class BlackboardArtifactNode extends DisplayableItemNode {
ss = Sheet.createPropertiesSet(); ss = Sheet.createPropertiesSet();
s.put(ss); s.put(ss);
} }
final String NO_DESCR = NbBundle.getMessage(this.getClass(), "BlackboardArtifactNode.noDesc.text"); final String NO_DESCR = NbBundle.getMessage(BlackboardArtifactNode.class, "BlackboardArtifactNode.noDesc.text");
Map<String, Object> map = new LinkedHashMap<>(); Map<String, Object> map = new LinkedHashMap<>();
fillPropertyMap(map, artifact); fillPropertyMap(map, artifact);
ss.put(new NodeProperty<>(NbBundle.getMessage(this.getClass(), "BlackboardArtifactNode.createSheet.srcFile.name"), ss.put(new NodeProperty<>(NbBundle.getMessage(BlackboardArtifactNode.class, "BlackboardArtifactNode.createSheet.srcFile.name"),
NbBundle.getMessage(this.getClass(), "BlackboardArtifactNode.createSheet.srcFile.displayName"), NbBundle.getMessage(BlackboardArtifactNode.class, "BlackboardArtifactNode.createSheet.srcFile.displayName"),
NO_DESCR, NO_DESCR,
this.getDisplayName())); this.getDisplayName()));
@ -222,13 +222,13 @@ public class BlackboardArtifactNode extends DisplayableItemNode {
actualMimeType = ""; //NON-NLS actualMimeType = ""; //NON-NLS
} }
} }
ss.put(new NodeProperty<>(NbBundle.getMessage(this.getClass(), "BlackboardArtifactNode.createSheet.ext.name"), ss.put(new NodeProperty<>(NbBundle.getMessage(BlackboardArtifactNode.class, "BlackboardArtifactNode.createSheet.ext.name"),
NbBundle.getMessage(this.getClass(), "BlackboardArtifactNode.createSheet.ext.displayName"), NbBundle.getMessage(BlackboardArtifactNode.class, "BlackboardArtifactNode.createSheet.ext.displayName"),
NO_DESCR, NO_DESCR,
ext)); ext));
ss.put(new NodeProperty<>( ss.put(new NodeProperty<>(
NbBundle.getMessage(this.getClass(), "BlackboardArtifactNode.createSheet.mimeType.name"), NbBundle.getMessage(BlackboardArtifactNode.class, "BlackboardArtifactNode.createSheet.mimeType.name"),
NbBundle.getMessage(this.getClass(), "BlackboardArtifactNode.createSheet.mimeType.displayName"), NbBundle.getMessage(BlackboardArtifactNode.class, "BlackboardArtifactNode.createSheet.mimeType.displayName"),
NO_DESCR, NO_DESCR,
actualMimeType)); actualMimeType));
} }
@ -243,32 +243,32 @@ public class BlackboardArtifactNode extends DisplayableItemNode {
if (sourcePath.isEmpty() == false) { if (sourcePath.isEmpty() == false) {
ss.put(new NodeProperty<>( ss.put(new NodeProperty<>(
NbBundle.getMessage(this.getClass(), "BlackboardArtifactNode.createSheet.filePath.name"), NbBundle.getMessage(BlackboardArtifactNode.class, "BlackboardArtifactNode.createSheet.filePath.name"),
NbBundle.getMessage(this.getClass(), "BlackboardArtifactNode.createSheet.filePath.displayName"), NbBundle.getMessage(BlackboardArtifactNode.class, "BlackboardArtifactNode.createSheet.filePath.displayName"),
NO_DESCR, NO_DESCR,
sourcePath)); sourcePath));
} }
if (Arrays.asList(SHOW_FILE_METADATA).contains(artifactTypeId)) { if (Arrays.asList(SHOW_FILE_METADATA).contains(artifactTypeId)) {
AbstractFile file = associated instanceof AbstractFile ? (AbstractFile) associated : null; AbstractFile file = associated instanceof AbstractFile ? (AbstractFile) associated : null;
ss.put(new NodeProperty<>(NbBundle.getMessage(this.getClass(), "ContentTagNode.createSheet.fileModifiedTime.name"), ss.put(new NodeProperty<>(NbBundle.getMessage(BlackboardArtifactNode.class, "ContentTagNode.createSheet.fileModifiedTime.name"),
NbBundle.getMessage(this.getClass(), "ContentTagNode.createSheet.fileModifiedTime.displayName"), NbBundle.getMessage(BlackboardArtifactNode.class, "ContentTagNode.createSheet.fileModifiedTime.displayName"),
"", "",
file != null ? ContentUtils.getStringTime(file.getMtime(), file) : "")); file != null ? ContentUtils.getStringTime(file.getMtime(), file) : ""));
ss.put(new NodeProperty<>(NbBundle.getMessage(this.getClass(), "ContentTagNode.createSheet.fileChangedTime.name"), ss.put(new NodeProperty<>(NbBundle.getMessage(BlackboardArtifactNode.class, "ContentTagNode.createSheet.fileChangedTime.name"),
NbBundle.getMessage(this.getClass(), "ContentTagNode.createSheet.fileChangedTime.displayName"), NbBundle.getMessage(BlackboardArtifactNode.class, "ContentTagNode.createSheet.fileChangedTime.displayName"),
"", "",
file != null ? ContentUtils.getStringTime(file.getCtime(), file) : "")); file != null ? ContentUtils.getStringTime(file.getCtime(), file) : ""));
ss.put(new NodeProperty<>(NbBundle.getMessage(this.getClass(), "ContentTagNode.createSheet.fileAccessedTime.name"), ss.put(new NodeProperty<>(NbBundle.getMessage(BlackboardArtifactNode.class, "ContentTagNode.createSheet.fileAccessedTime.name"),
NbBundle.getMessage(this.getClass(), "ContentTagNode.createSheet.fileAccessedTime.displayName"), NbBundle.getMessage(BlackboardArtifactNode.class, "ContentTagNode.createSheet.fileAccessedTime.displayName"),
"", "",
file != null ? ContentUtils.getStringTime(file.getAtime(), file) : "")); file != null ? ContentUtils.getStringTime(file.getAtime(), file) : ""));
ss.put(new NodeProperty<>(NbBundle.getMessage(this.getClass(), "ContentTagNode.createSheet.fileCreatedTime.name"), ss.put(new NodeProperty<>(NbBundle.getMessage(BlackboardArtifactNode.class, "ContentTagNode.createSheet.fileCreatedTime.name"),
NbBundle.getMessage(this.getClass(), "ContentTagNode.createSheet.fileCreatedTime.displayName"), NbBundle.getMessage(BlackboardArtifactNode.class, "ContentTagNode.createSheet.fileCreatedTime.displayName"),
"", "",
file != null ? ContentUtils.getStringTime(file.getCrtime(), file) : "")); file != null ? ContentUtils.getStringTime(file.getCrtime(), file) : ""));
ss.put(new NodeProperty<>(NbBundle.getMessage(this.getClass(), "ContentTagNode.createSheet.fileSize.name"), ss.put(new NodeProperty<>(NbBundle.getMessage(BlackboardArtifactNode.class, "ContentTagNode.createSheet.fileSize.name"),
NbBundle.getMessage(this.getClass(), "ContentTagNode.createSheet.fileSize.displayName"), NbBundle.getMessage(BlackboardArtifactNode.class, "ContentTagNode.createSheet.fileSize.displayName"),
"", "",
associated.getSize())); associated.getSize()));
} }
@ -287,8 +287,8 @@ public class BlackboardArtifactNode extends DisplayableItemNode {
if (dataSourceStr.isEmpty() == false) { if (dataSourceStr.isEmpty() == false) {
ss.put(new NodeProperty<>( ss.put(new NodeProperty<>(
NbBundle.getMessage(this.getClass(), "BlackboardArtifactNode.createSheet.dataSrc.name"), NbBundle.getMessage(BlackboardArtifactNode.class, "BlackboardArtifactNode.createSheet.dataSrc.name"),
NbBundle.getMessage(this.getClass(), "BlackboardArtifactNode.createSheet.dataSrc.displayName"), NbBundle.getMessage(BlackboardArtifactNode.class, "BlackboardArtifactNode.createSheet.dataSrc.displayName"),
NO_DESCR, NO_DESCR,
dataSourceStr)); dataSourceStr));
} }

View File

@ -118,17 +118,6 @@ FileSize.createSheet.filterType.displayName=Filter Type
FileSize.createSheet.filterType.desc=no description FileSize.createSheet.filterType.desc=no description
FileSize.exception.notSupported.msg=Not supported for this type of Displayable Item\: {0} FileSize.exception.notSupported.msg=Not supported for this type of Displayable Item\: {0}
FileTypeChildren.exception.notSupported.msg=Not supported for this type of Displayable Item\: {0} FileTypeChildren.exception.notSupported.msg=Not supported for this type of Displayable Item\: {0}
FileTypeExtensionFilters.tskImgFilter.text=Images
FileTypeExtensionFilters.tskVideoFilter.text=Videos
FileTypeExtensionFilters.tskAudioFilter.text=Audio
FileTypeExtensionFilters.tskArchiveFilter.text=Archives
FileTypeExtensionFilters.tskDocumentFilter.text=Documents
FileTypeExtensionFilters.tskExecFilter.text=Executable
FileTypeExtensionFilters.autDocHtmlFilter.text=HTML
FileTypeExtensionFilters.autDocOfficeFilter.text=Office
FileTypeExtensionFilters.autoDocPdfFilter.text=PDF
FileTypeExtensionFilters.autDocTxtFilter.text=Plain Text
FileTypeExtensionFilters.autDocRtfFilter.text=Rich Text
FileTypeNode.createSheet.filterType.name=Filter Type FileTypeNode.createSheet.filterType.name=Filter Type
FileTypeNode.createSheet.filterType.displayName=Filter Type FileTypeNode.createSheet.filterType.displayName=Filter Type
FileTypeNode.createSheet.filterType.desc=no description FileTypeNode.createSheet.filterType.desc=no description

View File

@ -0,0 +1,171 @@
package org.sleuthkit.autopsy.datamodel;
import com.google.common.collect.Range;
import com.google.common.collect.RangeMap;
import com.google.common.collect.TreeRangeMap;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Optional;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.annotation.concurrent.GuardedBy;
import org.apache.commons.csv.CSVFormat;
import org.apache.commons.csv.CSVParser;
import org.apache.commons.csv.CSVRecord;
import org.apache.commons.lang3.StringUtils;
import org.sleuthkit.autopsy.coreutils.MessageNotifyUtil;
import org.sleuthkit.autopsy.datamodel._private.BINRange;
public class CreditCards {
//Interface for objects that provide details about one or more BINs.
static public interface BankIdentificationNumber {
/**
* Get the city of the issuer.
*
* @return the city of the issuer.
*/
Optional<String> getBankCity();
/**
* Get the name of the issuer.
*
* @return the name of the issuer.
*/
Optional<String> getBankName();
/**
* Get the phone number of the issuer.
*
* @return the phone number of the issuer.
*/
Optional<String> getBankPhoneNumber();
/**
* Get the URL of the issuer.
*
* @return the URL of the issuer.
*/
Optional<String> getBankURL();
/**
* Get the brand of this BIN range.
*
* @return the brand of this BIN range.
*/
Optional<String> getBrand();
/**
* Get the type of card (credit vs debit) for this BIN range.
*
* @return the type of cards in this BIN range.
*/
Optional<String> getCardType();
/**
* Get the country of the issuer.
*
* @return the country of the issuer.
*/
Optional<String> getCountry();
/**
* Get the length of account numbers in this BIN range.
*
* NOTE: the length is currently unused, and not in the data file for
* any ranges. It could be quite helpfull for validation...
*
* @return the length of account numbers in this BIN range. Or an empty
* Optional if the length is unknown.
*
*/
Optional<Integer> getNumberLength();
/**
* Get the scheme this BIN range uses to amex,visa,mastercard, etc
*
* @return the scheme this BIN range uses.
*/
Optional<String> getScheme();
}
private static final Logger LOGGER = Logger.getLogger(CreditCards.class.getName());
/**
* Range Map from a (ranges of) BINs to data model object with details of
* the BIN, ie, bank name, phone, url, visa/amex/mastercard/...,
*/
@GuardedBy("CreditCards.class")
private final static RangeMap<Integer, BINRange> binRanges = TreeRangeMap.create();
/**
* Flag for if we have loaded the BINs from the file already.
*/
@GuardedBy("CreditCards.class")
private static boolean binsLoaded = false;
/**
* Load the BIN range information from disk. If the map has already been
* initialized, don't load again.
*/
synchronized private static void loadBINRanges() {
if (binsLoaded == false) {
try {
InputStreamReader in = new InputStreamReader(CreditCards.class.getResourceAsStream("ranges.csv")); //NON-NLS
CSVParser rangesParser = CSVFormat.RFC4180.withFirstRecordAsHeader().parse(in);
//parse each row and add to range map
for (CSVRecord record : rangesParser) {
/**
* Because ranges.csv allows both 6 and (the newer) 8 digit
* BINs, but we need a consistent length for the range map,
* we pad all the numbers out to 8 digits
*/
String start = StringUtils.rightPad(record.get("iin_start"), 8, "0"); //pad start with 0's //NON-NLS
//if there is no end listed, use start, since ranges will be closed.
String end = StringUtils.defaultIfBlank(record.get("iin_end"), start); //NON-NLS
end = StringUtils.rightPad(end, 8, "99"); //pad end with 9's //NON-NLS
final String numberLength = record.get("number_length"); //NON-NLS
try {
BINRange binRange = new BINRange(Integer.parseInt(start),
Integer.parseInt(end),
StringUtils.isBlank(numberLength) ? null : Integer.valueOf(numberLength),
record.get("scheme"), //NON-NLS
record.get("brand"), //NON-NLS
record.get("type"), //NON-NLS
record.get("country"), //NON-NLS
record.get("bank_name"), //NON-NLS
record.get("bank_url"), //NON-NLS
record.get("bank_phone"), //NON-NLS
record.get("bank_city")); //NON-NLS
binRanges.put(Range.closed(binRange.getBINstart(), binRange.getBINend()), binRange);
} catch (NumberFormatException numberFormatException) {
LOGGER.log(Level.WARNING, "Failed to parse BIN range: " + record.toString(), numberFormatException); //NON-NLS
}
binsLoaded = true;
}
} catch (IOException ex) {
LOGGER.log(Level.WARNING, "Failed to load BIN ranges form ranges.csv", ex); //NON-NLS
MessageNotifyUtil.Notify.warn("Credit Card Number Discovery", "There was an error loading Bank Identification Number information. Accounts will not have their BINs identified.");
}
}
}
/**
* Get an BINInfo object with details about the given BIN
*
* @param bin the BIN to get details of.
*
* @return
*/
synchronized static public BankIdentificationNumber getBINInfo(int bin) {
loadBINRanges();
return binRanges.get(bin);
}
}

View File

@ -18,6 +18,9 @@
*/ */
package org.sleuthkit.autopsy.datamodel; package org.sleuthkit.autopsy.datamodel;
import org.sleuthkit.autopsy.datamodel._private.AutopsyItemVisitor;
import org.sleuthkit.autopsy.datamodel._private.AutopsyVisitableItem;
/** /**
* Root node to store the data sources in a case * Root node to store the data sources in a case
*/ */

View File

@ -18,6 +18,8 @@
*/ */
package org.sleuthkit.autopsy.datamodel; package org.sleuthkit.autopsy.datamodel;
import org.sleuthkit.autopsy.datamodel._private.AutopsyItemVisitor;
import org.sleuthkit.autopsy.datamodel._private.AutopsyVisitableItem;
import java.beans.PropertyChangeEvent; import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener; import java.beans.PropertyChangeListener;
import java.util.ArrayList; import java.util.ArrayList;

View File

@ -22,6 +22,7 @@ import org.sleuthkit.autopsy.datamodel.DeletedContent.DeletedContentsChildren.De
import org.sleuthkit.autopsy.datamodel.DeletedContent.DeletedContentsNode; import org.sleuthkit.autopsy.datamodel.DeletedContent.DeletedContentsNode;
import org.sleuthkit.autopsy.datamodel.FileSize.FileSizeRootChildren.FileSizeNode; import org.sleuthkit.autopsy.datamodel.FileSize.FileSizeRootChildren.FileSizeNode;
import org.sleuthkit.autopsy.datamodel.FileSize.FileSizeRootNode; import org.sleuthkit.autopsy.datamodel.FileSize.FileSizeRootNode;
import org.sleuthkit.autopsy.datamodel._private.Accounts;
/** /**
* Visitor pattern that goes over all nodes in the directory tree. This includes * Visitor pattern that goes over all nodes in the directory tree. This includes
@ -127,7 +128,7 @@ public interface DisplayableItemNodeVisitor<T> {
*/ */
T visit(Accounts.AccountsRootNode accountRootNode); T visit(Accounts.AccountsRootNode accountRootNode);
T visit(Accounts.AccountTypeNode accountTypeNode); T visit(Accounts.CreditCardNumberAccountTypeNode accountTypeNode);
T visit(Accounts.ByBINNode byArtifactNode); T visit(Accounts.ByBINNode byArtifactNode);
@ -137,6 +138,8 @@ public interface DisplayableItemNodeVisitor<T> {
T visit(Accounts.BINNode binNode); T visit(Accounts.BINNode binNode);
T visit(Accounts.DefaultAccountTypeNode node);
/** /**
* Visitor with an implementable default behavior for all types. Override * Visitor with an implementable default behavior for all types. Override
* specific visit types to not use the default behavior. * specific visit types to not use the default behavior.
@ -350,7 +353,7 @@ public interface DisplayableItemNodeVisitor<T> {
} }
@Override @Override
public T visit(Accounts.AccountTypeNode node) { public T visit(Accounts.CreditCardNumberAccountTypeNode node) {
return defaultVisit(node); return defaultVisit(node);
} }
@ -378,5 +381,9 @@ public interface DisplayableItemNodeVisitor<T> {
public T visit(Accounts.BINNode node) { public T visit(Accounts.BINNode node) {
return defaultVisit(node); return defaultVisit(node);
} }
@Override
public T visit(Accounts.DefaultAccountTypeNode node) {
return defaultVisit(node);
}
} }
} }

View File

@ -18,6 +18,8 @@
*/ */
package org.sleuthkit.autopsy.datamodel; package org.sleuthkit.autopsy.datamodel;
import org.sleuthkit.autopsy.datamodel._private.AutopsyItemVisitor;
import org.sleuthkit.autopsy.datamodel._private.AutopsyVisitableItem;
import java.beans.PropertyChangeEvent; import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener; import java.beans.PropertyChangeListener;
import java.sql.ResultSet; import java.sql.ResultSet;

View File

@ -18,6 +18,8 @@
*/ */
package org.sleuthkit.autopsy.datamodel; package org.sleuthkit.autopsy.datamodel;
import org.sleuthkit.autopsy.datamodel._private.AutopsyItemVisitor;
import org.sleuthkit.autopsy.datamodel._private.AutopsyVisitableItem;
import java.beans.PropertyChangeEvent; import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener; import java.beans.PropertyChangeListener;
import java.util.ArrayList; import java.util.ArrayList;
@ -37,7 +39,7 @@ import org.sleuthkit.autopsy.coreutils.Logger;
import org.sleuthkit.autopsy.ingest.IngestManager; import org.sleuthkit.autopsy.ingest.IngestManager;
import org.sleuthkit.autopsy.ingest.ModuleDataEvent; import org.sleuthkit.autopsy.ingest.ModuleDataEvent;
import org.sleuthkit.datamodel.BlackboardArtifact; import org.sleuthkit.datamodel.BlackboardArtifact;
import static org.sleuthkit.datamodel.BlackboardArtifact.ARTIFACT_TYPE.TSK_CREDIT_CARD_ACCOUNT; import static org.sleuthkit.datamodel.BlackboardArtifact.ARTIFACT_TYPE.TSK_ACCOUNT;
import static org.sleuthkit.datamodel.BlackboardArtifact.ARTIFACT_TYPE.TSK_EMAIL_MSG; import static org.sleuthkit.datamodel.BlackboardArtifact.ARTIFACT_TYPE.TSK_EMAIL_MSG;
import static org.sleuthkit.datamodel.BlackboardArtifact.ARTIFACT_TYPE.TSK_GEN_INFO; import static org.sleuthkit.datamodel.BlackboardArtifact.ARTIFACT_TYPE.TSK_GEN_INFO;
import static org.sleuthkit.datamodel.BlackboardArtifact.ARTIFACT_TYPE.TSK_HASHSET_HIT; import static org.sleuthkit.datamodel.BlackboardArtifact.ARTIFACT_TYPE.TSK_HASHSET_HIT;
@ -201,7 +203,7 @@ public class ExtractedContent implements AutopsyVisitableItem {
doNotShow.add(new BlackboardArtifact.Type(TSK_KEYWORD_HIT)); doNotShow.add(new BlackboardArtifact.Type(TSK_KEYWORD_HIT));
doNotShow.add(new BlackboardArtifact.Type(TSK_INTERESTING_FILE_HIT)); doNotShow.add(new BlackboardArtifact.Type(TSK_INTERESTING_FILE_HIT));
doNotShow.add(new BlackboardArtifact.Type(TSK_INTERESTING_ARTIFACT_HIT)); doNotShow.add(new BlackboardArtifact.Type(TSK_INTERESTING_ARTIFACT_HIT));
doNotShow.add(new BlackboardArtifact.Type(TSK_CREDIT_CARD_ACCOUNT)); doNotShow.add(new BlackboardArtifact.Type(TSK_ACCOUNT));
} }
private final PropertyChangeListener pcl = (PropertyChangeEvent evt) -> { private final PropertyChangeListener pcl = (PropertyChangeEvent evt) -> {

View File

@ -18,6 +18,8 @@
*/ */
package org.sleuthkit.autopsy.datamodel; package org.sleuthkit.autopsy.datamodel;
import org.sleuthkit.autopsy.datamodel._private.AutopsyItemVisitor;
import org.sleuthkit.autopsy.datamodel._private.AutopsyVisitableItem;
import java.beans.PropertyChangeEvent; import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener; import java.beans.PropertyChangeListener;
import java.util.ArrayList; import java.util.ArrayList;

View File

@ -18,6 +18,7 @@
*/ */
package org.sleuthkit.autopsy.datamodel; package org.sleuthkit.autopsy.datamodel;
import org.sleuthkit.autopsy.datamodel._private.FileTypeExtensionFilters;
import java.util.List; import java.util.List;
import java.util.Observable; import java.util.Observable;
import java.util.Observer; import java.util.Observer;

View File

@ -18,6 +18,7 @@
*/ */
package org.sleuthkit.autopsy.datamodel; package org.sleuthkit.autopsy.datamodel;
import org.sleuthkit.autopsy.datamodel._private.FileTypeExtensionFilters;
import java.beans.PropertyChangeEvent; import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener; import java.beans.PropertyChangeListener;
import java.util.Arrays; import java.util.Arrays;

View File

@ -18,6 +18,8 @@
*/ */
package org.sleuthkit.autopsy.datamodel; package org.sleuthkit.autopsy.datamodel;
import org.sleuthkit.autopsy.datamodel._private.AutopsyItemVisitor;
import org.sleuthkit.autopsy.datamodel._private.AutopsyVisitableItem;
import java.beans.PropertyChangeEvent; import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener; import java.beans.PropertyChangeListener;
import java.sql.ResultSet; import java.sql.ResultSet;

View File

@ -18,6 +18,8 @@
*/ */
package org.sleuthkit.autopsy.datamodel; package org.sleuthkit.autopsy.datamodel;
import org.sleuthkit.autopsy.datamodel._private.AutopsyItemVisitor;
import org.sleuthkit.autopsy.datamodel._private.AutopsyVisitableItem;
import java.beans.PropertyChangeEvent; import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener; import java.beans.PropertyChangeListener;
import java.sql.ResultSet; import java.sql.ResultSet;

View File

@ -18,6 +18,8 @@
*/ */
package org.sleuthkit.autopsy.datamodel; package org.sleuthkit.autopsy.datamodel;
import org.sleuthkit.autopsy.datamodel._private.AutopsyItemVisitor;
import org.sleuthkit.autopsy.datamodel._private.AutopsyVisitableItem;
import java.beans.PropertyChangeEvent; import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener; import java.beans.PropertyChangeListener;
import java.sql.ResultSet; import java.sql.ResultSet;

View File

@ -18,6 +18,7 @@
*/ */
package org.sleuthkit.autopsy.datamodel; package org.sleuthkit.autopsy.datamodel;
import org.sleuthkit.autopsy.datamodel._private.RecentFiles;
import java.sql.ResultSet; import java.sql.ResultSet;
import java.sql.SQLException; import java.sql.SQLException;
import java.util.Arrays; import java.util.Arrays;

View File

@ -28,7 +28,7 @@ import org.sleuthkit.autopsy.coreutils.Logger;
import org.openide.nodes.AbstractNode; import org.openide.nodes.AbstractNode;
import org.openide.nodes.ChildFactory; import org.openide.nodes.ChildFactory;
import org.openide.nodes.Node; import org.openide.nodes.Node;
import org.sleuthkit.autopsy.datamodel.RecentFiles.RecentFilesFilter; import org.sleuthkit.autopsy.datamodel._private.RecentFiles.RecentFilesFilter;
import org.sleuthkit.datamodel.AbstractFile; import org.sleuthkit.datamodel.AbstractFile;
import org.sleuthkit.datamodel.Content; import org.sleuthkit.datamodel.Content;
import org.sleuthkit.datamodel.ContentVisitor; import org.sleuthkit.datamodel.ContentVisitor;

View File

@ -25,7 +25,7 @@ import org.sleuthkit.autopsy.coreutils.Logger;
import org.openide.nodes.Children; import org.openide.nodes.Children;
import org.openide.nodes.Sheet; import org.openide.nodes.Sheet;
import org.openide.util.lookup.Lookups; import org.openide.util.lookup.Lookups;
import org.sleuthkit.autopsy.datamodel.RecentFiles.RecentFilesFilter; import org.sleuthkit.autopsy.datamodel._private.RecentFiles.RecentFilesFilter;
import org.sleuthkit.datamodel.SleuthkitCase; import org.sleuthkit.datamodel.SleuthkitCase;
/** /**

View File

@ -18,6 +18,8 @@
*/ */
package org.sleuthkit.autopsy.datamodel; package org.sleuthkit.autopsy.datamodel;
import org.sleuthkit.autopsy.datamodel._private.AutopsyItemVisitor;
import org.sleuthkit.autopsy.datamodel._private.AutopsyVisitableItem;
import java.awt.Desktop; import java.awt.Desktop;
import java.awt.event.ActionEvent; import java.awt.event.ActionEvent;
import java.beans.PropertyChangeEvent; import java.beans.PropertyChangeEvent;

View File

@ -18,6 +18,8 @@
*/ */
package org.sleuthkit.autopsy.datamodel; package org.sleuthkit.autopsy.datamodel;
import org.sleuthkit.autopsy.datamodel._private.AutopsyItemVisitor;
import org.sleuthkit.autopsy.datamodel._private.AutopsyVisitableItem;
import org.sleuthkit.datamodel.SleuthkitCase; import org.sleuthkit.datamodel.SleuthkitCase;
/** /**

View File

@ -18,6 +18,7 @@
*/ */
package org.sleuthkit.autopsy.datamodel; package org.sleuthkit.autopsy.datamodel;
import org.sleuthkit.autopsy.datamodel._private.Accounts;
import java.util.Arrays; import java.util.Arrays;
import org.openide.nodes.Sheet; import org.openide.nodes.Sheet;
import org.openide.util.NbBundle; import org.openide.util.NbBundle;

View File

@ -18,6 +18,8 @@
*/ */
package org.sleuthkit.autopsy.datamodel; package org.sleuthkit.autopsy.datamodel;
import org.sleuthkit.autopsy.datamodel._private.AutopsyItemVisitor;
import org.sleuthkit.autopsy.datamodel._private.AutopsyVisitableItem;
import java.beans.PropertyChangeEvent; import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener; import java.beans.PropertyChangeListener;
import java.util.Collections; import java.util.Collections;

View File

@ -18,6 +18,8 @@
*/ */
package org.sleuthkit.autopsy.datamodel; package org.sleuthkit.autopsy.datamodel;
import org.sleuthkit.autopsy.datamodel._private.AutopsyItemVisitor;
import org.sleuthkit.autopsy.datamodel._private.AutopsyVisitableItem;
import org.sleuthkit.datamodel.SleuthkitCase; import org.sleuthkit.datamodel.SleuthkitCase;
/** /**

View File

@ -18,6 +18,7 @@
*/ */
package org.sleuthkit.autopsy.datamodel; package org.sleuthkit.autopsy.datamodel;
import org.sleuthkit.autopsy.datamodel._private.FileTypeExtensionFilters;
import java.util.Arrays; import java.util.Arrays;
import org.openide.nodes.Sheet; import org.openide.nodes.Sheet;
import org.openide.util.NbBundle; import org.openide.util.NbBundle;

File diff suppressed because it is too large Load Diff

View File

@ -16,14 +16,27 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
package org.sleuthkit.autopsy.datamodel; package org.sleuthkit.autopsy.datamodel._private;
import org.sleuthkit.autopsy.datamodel.DataSources;
import org.sleuthkit.autopsy.datamodel.DeletedContent;
import org.sleuthkit.autopsy.datamodel.EmailExtracted;
import org.sleuthkit.autopsy.datamodel.ExtractedContent;
import org.sleuthkit.autopsy.datamodel.FileSize;
import org.sleuthkit.autopsy.datamodel.HashsetHits;
import org.sleuthkit.autopsy.datamodel.InterestingHits;
import org.sleuthkit.autopsy.datamodel.KeywordHits;
import org.sleuthkit.autopsy.datamodel.Reports;
import org.sleuthkit.autopsy.datamodel.Results;
import org.sleuthkit.autopsy.datamodel.Tags;
import org.sleuthkit.autopsy.datamodel.Views;
/** /**
* This visitor goes over the AutopsyVisitableItems, which are currently the * This visitor goes over the AutopsyVisitableItems, which are currently the
* nodes in the tree that are structural and not nodes that are from * nodes in the tree that are structural and not nodes that are from
* Sleuthkit-based data model objects. * Sleuthkit-based data model objects.
*/ */
interface AutopsyItemVisitor<T> { public interface AutopsyItemVisitor<T> {
T visit(DataSources i); T visit(DataSources i);

View File

@ -16,13 +16,14 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
package org.sleuthkit.autopsy.datamodel; package org.sleuthkit.autopsy.datamodel._private;
;
/** /**
* AutopsyVisitableItems are the nodes in the directory tree that are for * AutopsyVisitableItems are the nodes in the directory tree that are for
* structure only. They are not associated with content objects. * structure only. They are not associated with content objects.
*/ */
interface AutopsyVisitableItem { public interface AutopsyVisitableItem {
/** /**
* visitor pattern support * visitor pattern support

View File

@ -0,0 +1,146 @@
/*
* Autopsy Forensic Browser
*
* Copyright 2011-2016 Basis Technology Corp.
* Contact: carrier <at> sleuthkit <dot> org
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.sleuthkit.autopsy.datamodel._private;
import java.util.Optional;
import javax.annotation.concurrent.Immutable;
import org.apache.commons.lang3.StringUtils;
import org.sleuthkit.autopsy.datamodel.CreditCards;
/**
* Details of a range of Bank Identification Number(s) (BIN) used by a bank.
*/
@Immutable
public class BINRange implements CreditCards.BankIdentificationNumber {
private final int BINStart; //start of BIN range, 8 digits
private final int BINEnd; // end (incluse ) of BIN rnage, 8 digits
private final Integer numberLength; // the length of accounts numbers with this BIN, currently unused
/**
* AMEX, VISA, MASTERCARD, DINERS, DISCOVER, UNIONPAY
*/
private final String scheme;
private final String brand;
/**
* DEBIT, CREDIT
*/
private final String cardType;
private final String country;
private final String bankName;
private final String bankCity;
private final String bankURL;
private final String bankPhoneNumber;
/**
* Constructor
*
* @param BIN_start the first BIN in the range, must be 8 digits
* @param BIN_end the last(inclusive) BIN in the range, must be 8
* digits
* @param number_length the length of account numbers in this BIN range
* @param scheme amex/visa/mastercard/etc
* @param brand the brand of this BIN range
* @param type credit vs debit
* @param country the country of the issuer
* @param bank_name the name of the issuer
* @param bank_url the url of the issuer
* @param bank_phone the phone number of the issuer
* @param bank_city the city of the issuer
*/
public BINRange(int BIN_start, int BIN_end, Integer number_length, String scheme, String brand, String type, String country, String bank_name, String bank_url, String bank_phone, String bank_city) {
this.BINStart = BIN_start;
this.BINEnd = BIN_end;
this.numberLength = number_length;
this.scheme = StringUtils.defaultIfBlank(scheme, null);
this.brand = StringUtils.defaultIfBlank(brand, null);
this.cardType = StringUtils.defaultIfBlank(type, null);
this.country = StringUtils.defaultIfBlank(country, null);
this.bankName = StringUtils.defaultIfBlank(bank_name, null);
this.bankURL = StringUtils.defaultIfBlank(bank_url, null);
this.bankPhoneNumber = StringUtils.defaultIfBlank(bank_phone, null);
this.bankCity = StringUtils.defaultIfBlank(bank_city, null);
}
/**
* Get the first BIN in this range
*
* @return the first BIN in this range.
*/
public int getBINstart() {
return BINStart;
}
/**
* Get the last (inclusive) BIN in this range.
*
* @return the last (inclusive) BIN in this range.
*/
public int getBINend() {
return BINEnd;
}
@Override
public Optional<Integer> getNumberLength() {
return Optional.ofNullable(numberLength);
}
@Override
public Optional<String> getScheme() {
return Optional.ofNullable(scheme);
}
@Override
public Optional<String> getBrand() {
return Optional.ofNullable(brand);
}
@Override
public Optional<String> getCardType() {
return Optional.ofNullable(cardType);
}
@Override
public Optional<String> getCountry() {
return Optional.ofNullable(country);
}
@Override
public Optional<String> getBankName() {
return Optional.ofNullable(bankName);
}
@Override
public Optional<String> getBankURL() {
return Optional.ofNullable(bankURL);
}
@Override
public Optional<String> getBankPhoneNumber() {
return Optional.ofNullable(bankPhoneNumber);
}
@Override
public Optional<String> getBankCity() {
return Optional.ofNullable(bankCity);
}
}

View File

@ -0,0 +1,12 @@
FileTypeExtensionFilters.tskImgFilter.text=Images
FileTypeExtensionFilters.tskVideoFilter.text=Videos
FileTypeExtensionFilters.tskAudioFilter.text=Audio
FileTypeExtensionFilters.tskArchiveFilter.text=Archives
FileTypeExtensionFilters.tskDocumentFilter.text=Documents
FileTypeExtensionFilters.tskExecFilter.text=Executable
FileTypeExtensionFilters.autDocHtmlFilter.text=HTML
FileTypeExtensionFilters.autDocOfficeFilter.text=Office
FileTypeExtensionFilters.autoDocPdfFilter.text=PDF
FileTypeExtensionFilters.autDocTxtFilter.text=Plain Text
FileTypeExtensionFilters.autDocRtfFilter.text=Rich Text

View File

@ -16,20 +16,20 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
package org.sleuthkit.autopsy.datamodel; package org.sleuthkit.autopsy.datamodel._private;
import java.util.Arrays; import java.util.Arrays;
import java.util.List; import java.util.List;
import org.openide.util.NbBundle; import org.openide.util.NbBundle;
import org.sleuthkit.autopsy.datamodel.FileTypeExtensions;
import org.sleuthkit.datamodel.SleuthkitCase; import org.sleuthkit.datamodel.SleuthkitCase;
/** /**
* Filters database results by file extension. * Filters database results by file extension.
*/ */
class FileTypeExtensionFilters implements AutopsyVisitableItem { public class FileTypeExtensionFilters implements AutopsyVisitableItem {
private SleuthkitCase skCase; private final SleuthkitCase skCase;
// root node filters // root node filters
public enum RootFilter implements AutopsyVisitableItem, SearchFilterInterface { public enum RootFilter implements AutopsyVisitableItem, SearchFilterInterface {
@ -53,10 +53,10 @@ class FileTypeExtensionFilters implements AutopsyVisitableItem {
NbBundle.getMessage(FileTypeExtensionFilters.class, "FileTypeExtensionFilters.tskExecFilter.text"), NbBundle.getMessage(FileTypeExtensionFilters.class, "FileTypeExtensionFilters.tskExecFilter.text"),
Arrays.asList(".exe", ".dll", ".bat", ".cmd", ".com")); //NON-NLS Arrays.asList(".exe", ".dll", ".bat", ".cmd", ".com")); //NON-NLS
private int id; private final int id;
private String name; private final String name;
private String displayName; private final String displayName;
private List<String> filter; private final List<String> filter;
private RootFilter(int id, String name, String displayName, List<String> filter) { private RootFilter(int id, String name, String displayName, List<String> filter) {
this.id = id; this.id = id;
@ -110,10 +110,10 @@ class FileTypeExtensionFilters implements AutopsyVisitableItem {
NbBundle.getMessage(FileTypeExtensionFilters.class, "FileTypeExtensionFilters.autDocRtfFilter.text"), NbBundle.getMessage(FileTypeExtensionFilters.class, "FileTypeExtensionFilters.autDocRtfFilter.text"),
Arrays.asList(".rtf")); //NON-NLS Arrays.asList(".rtf")); //NON-NLS
private int id; private final int id;
private String name; private final String name;
private String displayName; private final String displayName;
private List<String> filter; private final List<String> filter;
private DocumentFilter(int id, String name, String displayName, List<String> filter) { private DocumentFilter(int id, String name, String displayName, List<String> filter) {
this.id = id; this.id = id;
@ -157,10 +157,10 @@ class FileTypeExtensionFilters implements AutopsyVisitableItem {
ExecutableFilter_CMD(3, "ExecutableFilter_CMD", ".cmd", Arrays.asList(".cmd")), //NON-NLS ExecutableFilter_CMD(3, "ExecutableFilter_CMD", ".cmd", Arrays.asList(".cmd")), //NON-NLS
ExecutableFilter_COM(4, "ExecutableFilter_COM", ".com", Arrays.asList(".com")); //NON-NLS ExecutableFilter_COM(4, "ExecutableFilter_COM", ".com", Arrays.asList(".com")); //NON-NLS
private int id; private final int id;
private String name; private final String name;
private String displayName; private final String displayName;
private List<String> filter; private final List<String> filter;
private ExecutableFilter(int id, String name, String displayName, List<String> filter) { private ExecutableFilter(int id, String name, String displayName, List<String> filter) {
this.id = id; this.id = id;
@ -208,7 +208,7 @@ class FileTypeExtensionFilters implements AutopsyVisitableItem {
return this.skCase; return this.skCase;
} }
interface SearchFilterInterface { public interface SearchFilterInterface {
public String getName(); public String getName();

View File

@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
package org.sleuthkit.autopsy.datamodel; package org.sleuthkit.autopsy.datamodel._private;
import org.openide.util.NbBundle; import org.openide.util.NbBundle;
import org.sleuthkit.datamodel.SleuthkitCase; import org.sleuthkit.datamodel.SleuthkitCase;
@ -25,7 +25,7 @@ import org.sleuthkit.datamodel.SleuthkitCase;
* Recent files node support NOTE: As of june '15 we do not display this in the * Recent files node support NOTE: As of june '15 we do not display this in the
* tree. It can be added back when we have filtering in the results area. * tree. It can be added back when we have filtering in the results area.
*/ */
class RecentFiles implements AutopsyVisitableItem { public class RecentFiles implements AutopsyVisitableItem {
SleuthkitCase skCase; SleuthkitCase skCase;

View File

@ -37,38 +37,15 @@ import org.sleuthkit.autopsy.coreutils.ContextMenuExtensionPoint;
import org.sleuthkit.autopsy.coreutils.Logger; import org.sleuthkit.autopsy.coreutils.Logger;
import org.sleuthkit.autopsy.datamodel.AbstractAbstractFileNode.AbstractFilePropertyType; import org.sleuthkit.autopsy.datamodel.AbstractAbstractFileNode.AbstractFilePropertyType;
import org.sleuthkit.autopsy.datamodel.AbstractFsContentNode; import org.sleuthkit.autopsy.datamodel.AbstractFsContentNode;
import org.sleuthkit.autopsy.datamodel.Accounts;
import org.sleuthkit.autopsy.datamodel.BlackboardArtifactNode; import org.sleuthkit.autopsy.datamodel.BlackboardArtifactNode;
import org.sleuthkit.autopsy.datamodel.DeletedContent.DeletedContentsChildren.DeletedContentNode;
import org.sleuthkit.autopsy.datamodel.DeletedContent.DeletedContentsNode;
import org.sleuthkit.autopsy.datamodel.DirectoryNode; import org.sleuthkit.autopsy.datamodel.DirectoryNode;
import org.sleuthkit.autopsy.datamodel.DisplayableItemNode; import org.sleuthkit.autopsy.datamodel.DisplayableItemNode;
import org.sleuthkit.autopsy.datamodel.DisplayableItemNodeVisitor; import org.sleuthkit.autopsy.datamodel.DisplayableItemNodeVisitor;
import org.sleuthkit.autopsy.datamodel.EmailExtracted;
import org.sleuthkit.autopsy.datamodel.EmailExtracted.AccountNode;
import org.sleuthkit.autopsy.datamodel.EmailExtracted.FolderNode;
import org.sleuthkit.autopsy.datamodel.ExtractedContent;
import org.sleuthkit.autopsy.datamodel.ExtractedContent.TypeNode;
import org.sleuthkit.autopsy.datamodel.FileNode; import org.sleuthkit.autopsy.datamodel.FileNode;
import org.sleuthkit.autopsy.datamodel.FileSize.FileSizeRootChildren.FileSizeNode;
import org.sleuthkit.autopsy.datamodel.FileSize.FileSizeRootNode;
import org.sleuthkit.autopsy.datamodel.FileTypeNode;
import org.sleuthkit.autopsy.datamodel.FileTypesNode;
import org.sleuthkit.autopsy.datamodel.HashsetHits;
import org.sleuthkit.autopsy.datamodel.HashsetHits.HashsetNameNode;
import org.sleuthkit.autopsy.datamodel.ImageNode;
import org.sleuthkit.autopsy.datamodel.InterestingHits;
import org.sleuthkit.autopsy.datamodel.KeywordHits;
import org.sleuthkit.autopsy.datamodel.KeywordHits.ListNode;
import org.sleuthkit.autopsy.datamodel.KeywordHits.TermNode;
import org.sleuthkit.autopsy.datamodel.LayoutFileNode; import org.sleuthkit.autopsy.datamodel.LayoutFileNode;
import org.sleuthkit.autopsy.datamodel.LocalFileNode; import org.sleuthkit.autopsy.datamodel.LocalFileNode;
import org.sleuthkit.autopsy.datamodel.RecentFilesFilterNode;
import org.sleuthkit.autopsy.datamodel.RecentFilesNode;
import org.sleuthkit.autopsy.datamodel.Reports; import org.sleuthkit.autopsy.datamodel.Reports;
import org.sleuthkit.autopsy.datamodel.Tags;
import org.sleuthkit.autopsy.datamodel.VirtualDirectoryNode; import org.sleuthkit.autopsy.datamodel.VirtualDirectoryNode;
import org.sleuthkit.autopsy.datamodel.VolumeNode;
import org.sleuthkit.datamodel.AbstractFile; import org.sleuthkit.datamodel.AbstractFile;
import org.sleuthkit.datamodel.BlackboardArtifact; import org.sleuthkit.datamodel.BlackboardArtifact;
import org.sleuthkit.datamodel.BlackboardAttribute; import org.sleuthkit.datamodel.BlackboardAttribute;
@ -301,112 +278,12 @@ public class DataResultFilterNode extends FilterNode {
*/ */
private class GetPreferredActionsDisplayableItemNodeVisitor extends DisplayableItemNodeVisitor.Default<AbstractAction> { private class GetPreferredActionsDisplayableItemNodeVisitor extends DisplayableItemNodeVisitor.Default<AbstractAction> {
@Override
public AbstractAction visit(ImageNode in) {
return openChild(in);
}
@Override
public AbstractAction visit(VolumeNode vn) {
return openChild(vn);
}
@Override
public AbstractAction visit(ExtractedContent.RootNode ecn) {
return openChild(ecn);
}
@Override
public AbstractAction visit(KeywordHits.RootNode khrn) {
return openChild(khrn);
}
@Override
public AbstractAction visit(HashsetHits.RootNode hhrn) {
return openChild(hhrn);
}
@Override
public AbstractAction visit(HashsetNameNode hhsn) {
return openChild(hhsn);
}
@Override
public AbstractAction visit(InterestingHits.RootNode iarn) {
return openChild(iarn);
}
@Override
public AbstractAction visit(InterestingHits.SetNameNode iasn) {
return openChild(iasn);
}
@Override
public AbstractAction visit(EmailExtracted.RootNode eern) {
return openChild(eern);
}
@Override
public AbstractAction visit(AccountNode eean) {
return openChild(eean);
}
@Override
public AbstractAction visit(FolderNode eefn) {
return openChild(eefn);
}
@Override
public AbstractAction visit(RecentFilesNode rfn) {
return openChild(rfn);
}
@Override
public AbstractAction visit(DeletedContentsNode dcn) {
return openChild(dcn);
}
@Override
public AbstractAction visit(DeletedContentNode dcn) {
return openChild(dcn);
}
@Override
public AbstractAction visit(FileSizeRootNode fsrn) {
return openChild(fsrn);
}
@Override
public AbstractAction visit(FileSizeNode fsn) {
return openChild(fsn);
}
@Override @Override
public AbstractAction visit(BlackboardArtifactNode ban) { public AbstractAction visit(BlackboardArtifactNode ban) {
return new ViewContextAction( return new ViewContextAction(
NbBundle.getMessage(this.getClass(), "DataResultFilterNode.action.viewInDir.text"), ban); NbBundle.getMessage(this.getClass(), "DataResultFilterNode.action.viewInDir.text"), ban);
} }
@Override
public AbstractAction visit(TypeNode atn) {
return openChild(atn);
}
@Override
public AbstractAction visit(Tags.TagNameNode node) {
return openChild(node);
}
@Override
public AbstractAction visit(Tags.ContentTagTypeNode node) {
return openChild(node);
}
@Override
public AbstractAction visit(Tags.BlackboardArtifactTagTypeNode node) {
return openChild(node);
}
@Override @Override
public AbstractAction visit(DirectoryNode dn) { public AbstractAction visit(DirectoryNode dn) {
if (dn.getDisplayName().equals(DirectoryNode.DOTDOTDIR)) { if (dn.getDisplayName().equals(DirectoryNode.DOTDOTDIR)) {
@ -418,11 +295,6 @@ public class DataResultFilterNode extends FilterNode {
} }
} }
@Override
public AbstractAction visit(VirtualDirectoryNode ldn) {
return openChild(ldn);
}
@Override @Override
public AbstractAction visit(FileNode fn) { public AbstractAction visit(FileNode fn) {
if (fn.hasContentChildren()) { if (fn.hasContentChildren()) {
@ -441,69 +313,14 @@ public class DataResultFilterNode extends FilterNode {
} }
} }
@Override
public AbstractAction visit(FileTypeNode fsfn) {
return openChild(fsfn);
}
@Override
public AbstractAction visit(FileTypesNode sfn) {
return openChild(sfn);
}
@Override
public AbstractAction visit(RecentFilesFilterNode rffn) {
return openChild(rffn);
}
@Override
public AbstractAction visit(ListNode khsn) {
return openChild(khsn);
}
@Override
public AbstractAction visit(TermNode khmln) {
return openChild(khmln);
}
@Override @Override
public AbstractAction visit(Reports.ReportNode reportNode) { public AbstractAction visit(Reports.ReportNode reportNode) {
return reportNode.getPreferredAction(); return reportNode.getPreferredAction();
} }
@Override
public AbstractAction visit(Accounts.BINNode node) {
return openChild(node);
}
@Override
public AbstractAction visit(Accounts.FileWithCCNNode node) {
return openChild(node);
}
@Override
public AbstractAction visit(Accounts.ByFileNode node) {
return openChild(node);
}
@Override
public AbstractAction visit(Accounts.ByBINNode node) {
return openChild(node);
}
@Override
public AbstractAction visit(Accounts.AccountsRootNode node) {
return openChild(node);
}
@Override
public AbstractAction visit(Accounts.AccountTypeNode node) {
return openChild(node);
}
@Override @Override
protected AbstractAction defaultVisit(DisplayableItemNode c) { protected AbstractAction defaultVisit(DisplayableItemNode c) {
return null; return openChild(c);
} }
/** /**

View File

@ -57,7 +57,6 @@ import org.sleuthkit.autopsy.corecomponents.DataResultTopComponent;
import org.sleuthkit.autopsy.corecomponents.TableFilterNode; import org.sleuthkit.autopsy.corecomponents.TableFilterNode;
import org.sleuthkit.autopsy.coreutils.Logger; import org.sleuthkit.autopsy.coreutils.Logger;
import org.sleuthkit.autopsy.coreutils.MessageNotifyUtil; import org.sleuthkit.autopsy.coreutils.MessageNotifyUtil;
import org.sleuthkit.autopsy.datamodel.Accounts;
import org.sleuthkit.autopsy.datamodel.BlackboardArtifactNode; import org.sleuthkit.autopsy.datamodel.BlackboardArtifactNode;
import org.sleuthkit.autopsy.datamodel.DataSources; import org.sleuthkit.autopsy.datamodel.DataSources;
import org.sleuthkit.autopsy.datamodel.DataSourcesNode; import org.sleuthkit.autopsy.datamodel.DataSourcesNode;
@ -71,6 +70,7 @@ import org.sleuthkit.autopsy.datamodel.RootContentChildren;
import org.sleuthkit.autopsy.datamodel.Tags; import org.sleuthkit.autopsy.datamodel.Tags;
import org.sleuthkit.autopsy.datamodel.Views; import org.sleuthkit.autopsy.datamodel.Views;
import org.sleuthkit.autopsy.datamodel.ViewsNode; import org.sleuthkit.autopsy.datamodel.ViewsNode;
import org.sleuthkit.autopsy.datamodel._private.Accounts;
import org.sleuthkit.autopsy.ingest.IngestManager; import org.sleuthkit.autopsy.ingest.IngestManager;
import org.sleuthkit.datamodel.BlackboardArtifact; import org.sleuthkit.datamodel.BlackboardArtifact;
import org.sleuthkit.datamodel.BlackboardAttribute; import org.sleuthkit.datamodel.BlackboardAttribute;

View File

@ -40,7 +40,7 @@ public class ExternalViewerAction extends AbstractAction {
private final static Logger logger = Logger.getLogger(ExternalViewerAction.class.getName()); private final static Logger logger = Logger.getLogger(ExternalViewerAction.class.getName());
private org.sleuthkit.datamodel.AbstractFile fileObject; private org.sleuthkit.datamodel.AbstractFile fileObject;
final static String[] EXECUTABLE_EXT = {".exe", ".dll", ".com", ".bat", ".msi", ".reg", ".scr"}; //NON-NLS final static String[] EXECUTABLE_EXT = {".exe", ".dll", ".com", ".bat", ".msi", ".reg", ".scr", ".cmd"}; //NON-NLS
public ExternalViewerAction(String title, Node fileNode) { public ExternalViewerAction(String title, Node fileNode) {
super(title); super(title);

View File

Before

Width:  |  Height:  |  Size: 1.4 KiB

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

View File

@ -254,8 +254,8 @@ class ReportHTML implements TableReportModule {
case TSK_REMOTE_DRIVE: case TSK_REMOTE_DRIVE:
in = getClass().getResourceAsStream("/org/sleuthkit/autopsy/report/images/drive_network.png"); //NON-NLS in = getClass().getResourceAsStream("/org/sleuthkit/autopsy/report/images/drive_network.png"); //NON-NLS
break; break;
case TSK_CREDIT_CARD_ACCOUNT: case TSK_ACCOUNT:
in = getClass().getResourceAsStream("/org/sleuthkit/autopsy/report/images/credit-card.png"); //NON-NLS in = getClass().getResourceAsStream("/org/sleuthkit/autopsy/report/images/accounts.png"); //NON-NLS
break; break;
default: default:
logger.log(Level.WARNING, "useDataTypeIcon: unhandled artifact type = " + dataType); //NON-NLS logger.log(Level.WARNING, "useDataTypeIcon: unhandled artifact type = " + dataType); //NON-NLS
@ -264,6 +264,16 @@ class ReportHTML implements TableReportModule {
iconFilePath = path + File.separator + iconFileName; iconFilePath = path + File.separator + iconFileName;
break; break;
} }
} else if (dataType.startsWith(ARTIFACT_TYPE.TSK_ACCOUNT.getDisplayName())) {
/* TSK_ACCOUNT artifacts get separated by their TSK_ACCOUNT_TYPE
* attribute, with a synthetic compound dataType name, so they are
* not caught by the switch statement above. For now we just give
* them all the general account icon, but we could do something else
* in the future.
*/
in = getClass().getResourceAsStream("/org/sleuthkit/autopsy/report/images/accounts.png"); //NON-NLS
iconFileName = "accounts.png"; //NON-NLS
iconFilePath = path + File.separator + iconFileName;
} else { // no defined artifact found for this dataType } else { // no defined artifact found for this dataType
in = getClass().getResourceAsStream("/org/sleuthkit/autopsy/report/images/star.png"); //NON-NLS in = getClass().getResourceAsStream("/org/sleuthkit/autopsy/report/images/star.png"); //NON-NLS
iconFileName = "star.png"; //NON-NLS iconFileName = "star.png"; //NON-NLS

View File

@ -18,12 +18,16 @@
*/ */
package org.sleuthkit.autopsy.report; package org.sleuthkit.autopsy.report;
import com.google.common.collect.ListMultimap;
import com.google.common.collect.Lists;
import com.google.common.collect.Multimaps;
import java.sql.ResultSet; import java.sql.ResultSet;
import java.sql.SQLException; import java.sql.SQLException;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.Collection; import java.util.Collection;
import java.util.Collections; import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap; import java.util.HashMap;
import java.util.HashSet; import java.util.HashSet;
import java.util.Iterator; import java.util.Iterator;
@ -43,6 +47,7 @@ import org.sleuthkit.datamodel.AbstractFile;
import org.sleuthkit.datamodel.BlackboardArtifact; import org.sleuthkit.datamodel.BlackboardArtifact;
import org.sleuthkit.datamodel.BlackboardArtifactTag; import org.sleuthkit.datamodel.BlackboardArtifactTag;
import org.sleuthkit.datamodel.BlackboardAttribute; import org.sleuthkit.datamodel.BlackboardAttribute;
import org.sleuthkit.datamodel.BlackboardAttribute.Type;
import org.sleuthkit.datamodel.Content; import org.sleuthkit.datamodel.Content;
import org.sleuthkit.datamodel.ContentTag; import org.sleuthkit.datamodel.ContentTag;
import org.sleuthkit.datamodel.SleuthkitCase; import org.sleuthkit.datamodel.SleuthkitCase;
@ -119,10 +124,10 @@ class TableReportGenerator {
*/ */
private void makeBlackboardArtifactTables() { private void makeBlackboardArtifactTables() {
// Make a comment string describing the tag names filter in effect. // Make a comment string describing the tag names filter in effect.
StringBuilder comment = new StringBuilder(); String comment = "";
if (!tagNamesFilter.isEmpty()) { if (!tagNamesFilter.isEmpty()) {
comment.append(NbBundle.getMessage(this.getClass(), "ReportGenerator.artifactTable.taggedResults.text")); comment += NbBundle.getMessage(this.getClass(), "ReportGenerator.artifactTable.taggedResults.text");
comment.append(makeCommaSeparatedList(tagNamesFilter)); comment += makeCommaSeparatedList(tagNamesFilter);
} }
// Add a table to the report for every enabled blackboard artifact type. // Add a table to the report for every enabled blackboard artifact type.
@ -139,10 +144,10 @@ class TableReportGenerator {
// Keyword hits and hashset hit artifacts get special handling. // Keyword hits and hashset hit artifacts get special handling.
if (type.getTypeID() == BlackboardArtifact.ARTIFACT_TYPE.TSK_KEYWORD_HIT.getTypeID()) { if (type.getTypeID() == BlackboardArtifact.ARTIFACT_TYPE.TSK_KEYWORD_HIT.getTypeID()) {
writeKeywordHits(tableReport, comment.toString(), tagNamesFilter); writeKeywordHits(tableReport, comment, tagNamesFilter);
continue; continue;
} else if (type.getTypeID() == BlackboardArtifact.ARTIFACT_TYPE.TSK_HASHSET_HIT.getTypeID()) { } else if (type.getTypeID() == BlackboardArtifact.ARTIFACT_TYPE.TSK_HASHSET_HIT.getTypeID()) {
writeHashsetHits(tableReport, comment.toString(), tagNamesFilter); writeHashsetHits(tableReport, comment, tagNamesFilter);
continue; continue;
} }
@ -152,54 +157,92 @@ class TableReportGenerator {
continue; continue;
} }
/* /* TSK_ACCOUNT artifacts get grouped by their TSK_ACCOUNT_TYPE
Gets all of the attribute types of this artifact type by adding * attribute, and then handed off to the standard method for writing
all of the types to a set * tables. */
*/ if (type.getTypeID() == BlackboardArtifact.ARTIFACT_TYPE.TSK_ACCOUNT.getTypeID()) {
Set<BlackboardAttribute.Type> attrTypeSet = new TreeSet<>((BlackboardAttribute.Type o1, BlackboardAttribute.Type o2) -> o1.getDisplayName().compareTo(o2.getDisplayName())); //Group account artifacts by their account type
for (ArtifactData data : artifactList) { ListMultimap<String, ArtifactData> groupedArtifacts = Multimaps.index(artifactList,
List<BlackboardAttribute> attributes = data.getAttributes(); artifactData -> {
for (BlackboardAttribute attribute : attributes) { try {
attrTypeSet.add(attribute.getAttributeType()); return artifactData.getArtifact().getAttribute(new BlackboardAttribute.Type(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_ACCOUNT_TYPE)).getValueString();
} catch (TskCoreException ex) {
logger.log(Level.SEVERE, "Unable to get value of TSK_ACCOUNT_TYPE attribute. Defaulting to \"unknown\"", ex);
return "unknown";
}
});
for (String accountType : groupedArtifacts.keySet()) {
/* If the report is a ReportHTML, the data type name
* eventualy makes it to useDataTypeIcon which expects but
* does not require a artifact name, so we make a synthetic
* compund name by appending a ":" and the account type.
*/
final String compundDataTypeName = BlackboardArtifact.ARTIFACT_TYPE.TSK_ACCOUNT.getDisplayName() + ": " + accountType;
writeTableForDataType(groupedArtifacts.get(accountType), type, compundDataTypeName, comment);
} }
} else {
//all other artifact types are sent to writeTableForDataType directly
writeTableForDataType(artifactList, type, type.getDisplayName(), comment);
} }
// Get the columns appropriate for the artifact type. This is
// used to get the data that will be in the cells below based on
// type, and display the column headers.
List<Column> columns = getArtifactTableColumns(type.getTypeID(), attrTypeSet);
if (columns.isEmpty()) {
continue;
}
columnHeaderMap.put(type.getTypeID(), columns);
// The artifact list is sorted now, as getting the row data is
// dependent on having the columns, which is necessary for
// sorting.
Collections.sort(artifactList);
List<String> columnHeaderNames = new ArrayList<>();
for (Column currColumn : columns) {
columnHeaderNames.add(currColumn.getColumnHeader());
}
tableReport.startDataType(type.getDisplayName(), comment.toString());
tableReport.startTable(columnHeaderNames);
for (ArtifactData artifactData : artifactList) {
// Get the row data for this artifact, and has the
// module add it.
List<String> rowData = artifactData.getRow();
if (rowData.isEmpty()) {
continue;
}
tableReport.addRow(rowData);
}
// Finish up this data type
progressPanel.increment();
tableReport.endTable();
tableReport.endDataType();
} }
} }
/**
*
* Write the given list of artifacts to the table for the given type.
*
* @param artifactList The List of artifacts to include in the table.
* @param type The Type of artifacts included in the table. All the
* artifacts in artifactList should be of this type.
* @param tableName The name of the table.
* @param comment A comment to put in the header.
*/
private void writeTableForDataType(List<ArtifactData> artifactList, BlackboardArtifact.Type type, String tableName, String comment) {
/*
* Make a sorted set of all of the attribute types that are on any of
* the given artifacts.
*/
Set<BlackboardAttribute.Type> attrTypeSet = new TreeSet<>(Comparator.comparing(BlackboardAttribute.Type::getDisplayName));
for (ArtifactData data : artifactList) {
List<BlackboardAttribute> attributes = data.getAttributes();
for (BlackboardAttribute attribute : attributes) {
attrTypeSet.add(attribute.getAttributeType());
}
}
/* Get the columns appropriate for the artifact type. This is used to
* get the data that will be in the cells below based on type, and
* display the column headers.
*/
List<Column> columns = getArtifactTableColumns(type.getTypeID(), attrTypeSet);
if (columns.isEmpty()) {
return;
}
columnHeaderMap.put(type.getTypeID(), columns);
/* The artifact list is sorted now, as getting the row data is dependent
* on having the columns, which is necessary for sorting.
*/
Collections.sort(artifactList);
tableReport.startDataType(tableName, comment);
tableReport.startTable(Lists.transform(columns, Column::getColumnHeader));
for (ArtifactData artifactData : artifactList) {
// Get the row data for this artifact, and has the
// module add it.
List<String> rowData = artifactData.getRow();
if (rowData.isEmpty()) {
return;
}
tableReport.addRow(rowData);
}
// Finish up this data type
progressPanel.increment();
tableReport.endTable();
tableReport.endDataType();
}
/** /**
* Make table for tagged files * Make table for tagged files
*/ */
@ -1449,8 +1492,9 @@ class TableReportGenerator {
columns.add(new AttributeColumn(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.remotePath"), columns.add(new AttributeColumn(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.remotePath"),
new BlackboardAttribute.Type(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_REMOTE_PATH))); new BlackboardAttribute.Type(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_REMOTE_PATH)));
} else if (artifactTypeId == BlackboardArtifact.ARTIFACT_TYPE.TSK_CREDIT_CARD_ACCOUNT.getTypeID()) { } else if (artifactTypeId == BlackboardArtifact.ARTIFACT_TYPE.TSK_ACCOUNT.getTypeID()) {
columns.add(new StatusColumn()); columns.add(new StatusColumn());
attributeTypeSet.remove(new Type(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_ACCOUNT_TYPE));
} else { } else {
// This is the case that it is a custom type. The reason an else is // This is the case that it is a custom type. The reason an else is
// necessary is to make sure that the source file column is added // necessary is to make sure that the source file column is added
@ -1584,6 +1628,7 @@ class TableReportGenerator {
} }
} }
private class AttributeColumn implements Column { private class AttributeColumn implements Column {
private final String columnHeader; private final String columnHeader;
@ -1643,10 +1688,6 @@ class TableReportGenerator {
@Override @Override
public String getCellData(ArtifactData artData) { public String getCellData(ArtifactData artData) {
return getFileUniquePath(artData.getContent()); return getFileUniquePath(artData.getContent());
/*else if (this.columnHeader.equals(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.tags"))) {
return makeCommaSeparatedList(artData.getTags());
}
return "";*/
} }
@Override @Override

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

View File

@ -37,7 +37,7 @@ import org.sleuthkit.autopsy.casemodule.Case;
import org.sleuthkit.autopsy.corecomponentinterfaces.DataContentViewer; import org.sleuthkit.autopsy.corecomponentinterfaces.DataContentViewer;
import org.sleuthkit.autopsy.coreutils.Logger; import org.sleuthkit.autopsy.coreutils.Logger;
import org.sleuthkit.datamodel.BlackboardArtifact; import org.sleuthkit.datamodel.BlackboardArtifact;
import static org.sleuthkit.datamodel.BlackboardArtifact.ARTIFACT_TYPE.TSK_CREDIT_CARD_ACCOUNT; import static org.sleuthkit.datamodel.BlackboardArtifact.ARTIFACT_TYPE.TSK_ACCOUNT;
import static org.sleuthkit.datamodel.BlackboardArtifact.ARTIFACT_TYPE.TSK_KEYWORD_HIT; import static org.sleuthkit.datamodel.BlackboardArtifact.ARTIFACT_TYPE.TSK_KEYWORD_HIT;
import org.sleuthkit.datamodel.BlackboardAttribute; import org.sleuthkit.datamodel.BlackboardAttribute;
import org.sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE; import org.sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE;
@ -127,7 +127,7 @@ public class ExtractedContentViewer implements DataContentViewer {
//if the node had artifacts in the lookup use them, other wise look up all credit card artifacts for the content. //if the node had artifacts in the lookup use them, other wise look up all credit card artifacts for the content.
Collection<? extends BlackboardArtifact> artifacts = nodeLookup.lookupAll(BlackboardArtifact.class); Collection<? extends BlackboardArtifact> artifacts = nodeLookup.lookupAll(BlackboardArtifact.class);
artifacts = (artifacts == null || artifacts.isEmpty()) artifacts = (artifacts == null || artifacts.isEmpty())
? content.getArtifacts(TSK_CREDIT_CARD_ACCOUNT) ? content.getArtifacts(TSK_ACCOUNT)
: artifacts; : artifacts;
/* /*
@ -140,7 +140,7 @@ public class ExtractedContentViewer implements DataContentViewer {
*/ */
for (BlackboardArtifact artifact : artifacts) { for (BlackboardArtifact artifact : artifacts) {
try { try {
BlackboardAttribute solrIDAttr = artifact.getAttribute(new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_SOLR_DOCUMENT_ID)); BlackboardAttribute solrIDAttr = artifact.getAttribute(new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_KEYWORD_SEARCH_DOCUMENT_ID));
if (solrIDAttr != null) { if (solrIDAttr != null) {
String valueString = solrIDAttr.getValueString(); String valueString = solrIDAttr.getValueString();
if (StringUtils.isNotBlank(valueString)) { if (StringUtils.isNotBlank(valueString)) {
@ -148,7 +148,7 @@ public class ExtractedContentViewer implements DataContentViewer {
} }
} }
BlackboardAttribute keyWordAttr = artifact.getAttribute(new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_ACCOUNT_NUMBER)); BlackboardAttribute keyWordAttr = artifact.getAttribute(new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_CARD_NUMBER));
if (keyWordAttr != null) { if (keyWordAttr != null) {
String valueString = keyWordAttr.getValueString(); String valueString = keyWordAttr.getValueString();
if (StringUtils.isNotBlank(valueString)) { if (StringUtils.isNotBlank(valueString)) {
@ -188,7 +188,7 @@ public class ExtractedContentViewer implements DataContentViewer {
* For keyword hit artifacts, add the text of the artifact that hit, * For keyword hit artifacts, add the text of the artifact that hit,
* not the hit artifact; otherwise add the text for the artifact. * not the hit artifact; otherwise add the text for the artifact.
*/ */
if (artifact.getArtifactTypeID() == TSK_KEYWORD_HIT.getTypeID() || artifact.getArtifactTypeID() == TSK_CREDIT_CARD_ACCOUNT.getTypeID()) { if (artifact.getArtifactTypeID() == TSK_KEYWORD_HIT.getTypeID() || artifact.getArtifactTypeID() == TSK_ACCOUNT.getTypeID()) {
try { try {
BlackboardAttribute attribute = artifact.getAttribute(TSK_ASSOCIATED_ARTIFACT_TYPE); BlackboardAttribute attribute = artifact.getAttribute(TSK_ASSOCIATED_ARTIFACT_TYPE);
if (attribute != null) { if (attribute != null) {
@ -296,7 +296,7 @@ public class ExtractedContentViewer implements DataContentViewer {
Collection<? extends BlackboardArtifact> artifacts = node.getLookup().lookupAll(BlackboardArtifact.class); Collection<? extends BlackboardArtifact> artifacts = node.getLookup().lookupAll(BlackboardArtifact.class);
if (artifacts != null) { if (artifacts != null) {
for (BlackboardArtifact art : artifacts) { for (BlackboardArtifact art : artifacts) {
if (art.getArtifactTypeID() == BlackboardArtifact.ARTIFACT_TYPE.TSK_CREDIT_CARD_ACCOUNT.getTypeID()) { if (art.getArtifactTypeID() == BlackboardArtifact.ARTIFACT_TYPE.TSK_ACCOUNT.getTypeID()) {
return true; return true;
} }
} }
@ -321,7 +321,7 @@ public class ExtractedContentViewer implements DataContentViewer {
if (art == null) { if (art == null) {
return 4; return 4;
} else if (art.getArtifactTypeID() == BlackboardArtifact.ARTIFACT_TYPE.TSK_KEYWORD_HIT.getTypeID() } else if (art.getArtifactTypeID() == BlackboardArtifact.ARTIFACT_TYPE.TSK_KEYWORD_HIT.getTypeID()
|| art.getArtifactTypeID() == BlackboardArtifact.ARTIFACT_TYPE.TSK_CREDIT_CARD_ACCOUNT.getTypeID()) { || art.getArtifactTypeID() == BlackboardArtifact.ARTIFACT_TYPE.TSK_ACCOUNT.getTypeID()) {
return 6; return 6;
} else { } else {
return 4; return 4;

View File

@ -122,7 +122,7 @@ abstract class KeywordSearchList {
//CCN //CCN
List<Keyword> ccns = new ArrayList<>(); List<Keyword> ccns = new ArrayList<>();
ccns.add(new Keyword(CCN_REGEX, false, BlackboardAttribute.ATTRIBUTE_TYPE.TSK_ACCOUNT_NUMBER)); ccns.add(new Keyword(CCN_REGEX, false, BlackboardAttribute.ATTRIBUTE_TYPE.TSK_CARD_NUMBER));
lockedLists.add("Credit Card Numbers"); lockedLists.add("Credit Card Numbers");
addList("Credit Card Numbers", ccns, true, false, true); addList("Credit Card Numbers", ccns, true, false, true);
} }

View File

@ -34,8 +34,9 @@ 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.autopsy.datamodel.Accounts; import org.sleuthkit.autopsy.datamodel.CreditCards;
import org.sleuthkit.datamodel.AbstractFile; import org.sleuthkit.datamodel.AbstractFile;
import org.sleuthkit.datamodel.Account;
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;
@ -52,8 +53,7 @@ final class TermComponentQuery implements KeywordSearchQuery {
private static final boolean DEBUG = Version.Type.DEVELOPMENT.equals(Version.getBuildType()); private static final boolean DEBUG = Version.Type.DEVELOPMENT.equals(Version.getBuildType());
private static final String MODULE_NAME = KeywordSearchModuleFactory.getModuleName(); private static final String MODULE_NAME = KeywordSearchModuleFactory.getModuleName();
private static final BlackboardAttribute.Type SOLR_DOCUMENT_ID_TYPE = new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_SOLR_DOCUMENT_ID); private static final BlackboardAttribute.Type KEYWORD_SEARCH_DOCUMENT_ID = new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_KEYWORD_SEARCH_DOCUMENT_ID);
private static final BlackboardAttribute.Type ACCOUNT_NUMBER_TYPE = new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_ACCOUNT_NUMBER);
//TODO: move these regex and the luhn check to a new class, something like: CreditCardNumberValidator //TODO: move these regex and the luhn check to a new class, something like: CreditCardNumberValidator
/* /*
@ -186,8 +186,13 @@ final class TermComponentQuery implements KeywordSearchQuery {
Collection<BlackboardAttribute> attributes = new ArrayList<>(); Collection<BlackboardAttribute> attributes = new ArrayList<>();
try { try {
//if the keyword hit matched the credit card number keyword/regex... //if the keyword hit matched the credit card number keyword/regex...
if (keyword.getType() == ATTRIBUTE_TYPE.TSK_ACCOUNT_NUMBER) { if (keyword.getType() == ATTRIBUTE_TYPE.TSK_CARD_NUMBER) {
newArtifact = hit.getContent().newArtifact(ARTIFACT_TYPE.TSK_CREDIT_CARD_ACCOUNT); newArtifact = hit.getContent().newArtifact(ARTIFACT_TYPE.TSK_ACCOUNT);
final BlackboardAttribute attr = new BlackboardAttribute(
new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_ACCOUNT_TYPE),
MODULE_NAME, Account.Type.CREDIT_CARD.name());
newArtifact.addAttribute(attr);
// make account artifact // make account artifact
//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());
@ -204,31 +209,31 @@ final class TermComponentQuery implements KeywordSearchQuery {
AbstractFile file = (AbstractFile) hit.getContent(); AbstractFile file = (AbstractFile) hit.getContent();
if (file.getType() == TskData.TSK_DB_FILES_TYPE_ENUM.UNUSED_BLOCKS if (file.getType() == TskData.TSK_DB_FILES_TYPE_ENUM.UNUSED_BLOCKS
|| file.getType() == TskData.TSK_DB_FILES_TYPE_ENUM.UNALLOC_BLOCKS) { || file.getType() == TskData.TSK_DB_FILES_TYPE_ENUM.UNALLOC_BLOCKS) {
newArtifact.addAttribute(new BlackboardAttribute(SOLR_DOCUMENT_ID_TYPE, MODULE_NAME, hit.getSolrDocumentId())); newArtifact.addAttribute(new BlackboardAttribute(KEYWORD_SEARCH_DOCUMENT_ID, MODULE_NAME, hit.getSolrDocumentId()));
} }
} }
String ccn = newArtifact.getAttribute(ACCOUNT_NUMBER_TYPE).getValueString(); String ccn = newArtifact.getAttribute(new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_CARD_NUMBER)).getValueString();
final int iin = Integer.parseInt(ccn.substring(0, 8)); final int bin = Integer.parseInt(ccn.substring(0, 8));
Accounts.IINInfo iinInfo = Accounts.getIINInfo(iin); CreditCards.BankIdentificationNumber binInfo = CreditCards.getBINInfo(bin);
if (iinInfo != null) { if (binInfo != null) {
iinInfo.getScheme().ifPresent(scheme binInfo.getScheme().ifPresent(scheme
-> addAttributeSafe(newArtifact, ATTRIBUTE_TYPE.TSK_CREDIT_CARD_SCHEME, scheme)); -> addAttributeSafe(newArtifact, ATTRIBUTE_TYPE.TSK_CARD_SCHEME, scheme));
iinInfo.getCardType().ifPresent(cardType binInfo.getCardType().ifPresent(cardType
-> addAttributeSafe(newArtifact, ATTRIBUTE_TYPE.TSK_PAYMENT_CARD_TYPE, cardType)); -> addAttributeSafe(newArtifact, ATTRIBUTE_TYPE.TSK_CARD_TYPE, cardType));
iinInfo.getBrand().ifPresent(brand binInfo.getBrand().ifPresent(brand
-> addAttributeSafe(newArtifact, ATTRIBUTE_TYPE.TSK_BRAND, brand)); -> addAttributeSafe(newArtifact, ATTRIBUTE_TYPE.TSK_BRAND_NAME, brand));
iinInfo.getBankName().ifPresent(bankName binInfo.getBankName().ifPresent(bankName
-> addAttributeSafe(newArtifact, ATTRIBUTE_TYPE.TSK_BANK_NAME, bankName)); -> addAttributeSafe(newArtifact, ATTRIBUTE_TYPE.TSK_BANK_NAME, bankName));
iinInfo.getBankPhoneNumber().ifPresent(phoneNumber binInfo.getBankPhoneNumber().ifPresent(phoneNumber
-> addAttributeSafe(newArtifact, ATTRIBUTE_TYPE.TSK_PHONE_NUMBER, phoneNumber)); -> addAttributeSafe(newArtifact, ATTRIBUTE_TYPE.TSK_PHONE_NUMBER, phoneNumber));
iinInfo.getBankURL().ifPresent(url binInfo.getBankURL().ifPresent(url
-> addAttributeSafe(newArtifact, ATTRIBUTE_TYPE.TSK_URL, url)); -> addAttributeSafe(newArtifact, ATTRIBUTE_TYPE.TSK_URL, url));
iinInfo.getCountry().ifPresent(country binInfo.getCountry().ifPresent(country
-> addAttributeSafe(newArtifact, ATTRIBUTE_TYPE.TSK_COUNTRY, country)); -> addAttributeSafe(newArtifact, ATTRIBUTE_TYPE.TSK_COUNTRY, country));
iinInfo.getBankCity().ifPresent(city binInfo.getBankCity().ifPresent(city
-> addAttributeSafe(newArtifact, ATTRIBUTE_TYPE.TSK_CITY, city)); -> addAttributeSafe(newArtifact, ATTRIBUTE_TYPE.TSK_CITY, city));
} }
} else { } else {
@ -323,7 +328,7 @@ final class TermComponentQuery implements KeywordSearchQuery {
for (Term term : terms) { for (Term term : terms) {
final String termStr = KeywordSearchUtil.escapeLuceneQuery(term.getTerm()); final String termStr = KeywordSearchUtil.escapeLuceneQuery(term.getTerm());
if (keyword.getType() == ATTRIBUTE_TYPE.TSK_ACCOUNT_NUMBER) { if (keyword.getType() == ATTRIBUTE_TYPE.TSK_CARD_NUMBER) {
//If the keyword is a credit card number, pass it through luhn validator //If the keyword is a credit card number, pass it through luhn validator
Matcher matcher = CCN_PATTERN.matcher(term.getTerm()); Matcher matcher = CCN_PATTERN.matcher(term.getTerm());
matcher.find(); matcher.find();
@ -383,7 +388,7 @@ final class TermComponentQuery implements KeywordSearchQuery {
BlackboardAttribute.Type type = new BlackboardAttribute.Type(attrType); BlackboardAttribute.Type type = new BlackboardAttribute.Type(attrType);
if (artifact.getAttribute(type) == null) { if (artifact.getAttribute(type) == null) {
String value = matcher.group(groupName); String value = matcher.group(groupName);
if (attrType.equals(ATTRIBUTE_TYPE.TSK_ACCOUNT_NUMBER)) { if (attrType.equals(ATTRIBUTE_TYPE.TSK_CARD_NUMBER)) {
value = CharMatcher.anyOf(" -").removeFrom(value); value = CharMatcher.anyOf(" -").removeFrom(value);
} }
if (StringUtils.isNotBlank(value)) { if (StringUtils.isNotBlank(value)) {
@ -404,11 +409,11 @@ final class TermComponentQuery implements KeywordSearchQuery {
*/ */
static private void parseTrack2Data(BlackboardArtifact artifact, Matcher matcher) 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_CARD_NUMBER, "accountNumber", matcher);
addAttributeIfNotAlreadyCaptured(artifact, ATTRIBUTE_TYPE.TSK_CREDIT_CARD_EXPIRATION, "expiration", matcher); addAttributeIfNotAlreadyCaptured(artifact, ATTRIBUTE_TYPE.TSK_CARD_EXPIRATION, "expiration", matcher);
addAttributeIfNotAlreadyCaptured(artifact, ATTRIBUTE_TYPE.TSK_CREDIT_CARD_SERVICE_CODE, "serviceCode", matcher); addAttributeIfNotAlreadyCaptured(artifact, ATTRIBUTE_TYPE.TSK_CARD_SERVICE_CODE, "serviceCode", matcher);
addAttributeIfNotAlreadyCaptured(artifact, ATTRIBUTE_TYPE.TSK_CREDIT_CARD_DISCRETIONARY, "discretionary", matcher); addAttributeIfNotAlreadyCaptured(artifact, ATTRIBUTE_TYPE.TSK_CARD_DISCRETIONARY, "discretionary", matcher);
addAttributeIfNotAlreadyCaptured(artifact, ATTRIBUTE_TYPE.TSK_CREDIT_CARD_LRC, "LRC", matcher); addAttributeIfNotAlreadyCaptured(artifact, ATTRIBUTE_TYPE.TSK_CARD_LRC, "LRC", matcher);
} }