Merge pull request #2365 from millmanorama/841-maintain-selection
841 maintain selection
@ -222,6 +222,10 @@
|
||||
</dependency>
|
||||
</module-dependencies>
|
||||
<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.casemodule</package>
|
||||
<package>org.sleuthkit.autopsy.casemodule.events</package>
|
||||
|
@ -1,7 +1,7 @@
|
||||
/*
|
||||
* Autopsy Forensic Browser
|
||||
*
|
||||
* Copyright 2013-15 Basis Technology Corp.
|
||||
* Copyright 2011-2016 Basis Technology Corp.
|
||||
* Contact: carrier <at> sleuthkit <dot> org
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
@ -19,8 +19,8 @@
|
||||
package org.sleuthkit.autopsy.actions;
|
||||
|
||||
import java.awt.event.ActionEvent;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.TreeMap;
|
||||
import java.util.logging.Level;
|
||||
import javax.swing.AbstractAction;
|
||||
import javax.swing.JMenu;
|
||||
@ -39,6 +39,7 @@ import org.sleuthkit.datamodel.TskCoreException;
|
||||
*/
|
||||
abstract class AddTagAction extends AbstractAction implements Presenter.Popup {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
private static final String NO_COMMENT = "";
|
||||
|
||||
AddTagAction(String menuText) {
|
||||
@ -82,15 +83,16 @@ abstract class AddTagAction extends AbstractAction implements Presenter.Popup {
|
||||
// to be reworked.
|
||||
private class TagMenu extends JMenu {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
TagMenu() {
|
||||
super(getActionDisplayName());
|
||||
|
||||
// Get the current set of tag names.
|
||||
TagsManager tagsManager = Case.getCurrentCase().getServices().getTagsManager();
|
||||
List<TagName> tagNames = null;
|
||||
Map<String, TagName> tagNamesMap = null;
|
||||
try {
|
||||
tagNames = tagsManager.getAllTagNames();
|
||||
Collections.sort(tagNames);
|
||||
tagNamesMap = new TreeMap<>(tagsManager.getDisplayNamesToTagNamesMap());
|
||||
} catch (TskCoreException ex) {
|
||||
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
|
||||
// the "Quick Tags" sub-menu. Selecting one of these menu items adds
|
||||
// a tag with the associated tag name.
|
||||
if (null != tagNames && !tagNames.isEmpty()) {
|
||||
for (final TagName tagName : tagNames) {
|
||||
JMenuItem tagNameItem = new JMenuItem(tagName.getDisplayName());
|
||||
if (null != tagNamesMap && !tagNamesMap.isEmpty()) {
|
||||
for (Map.Entry<String, TagName> entry : tagNamesMap.entrySet()) {
|
||||
JMenuItem tagNameItem = new JMenuItem(entry.getKey());
|
||||
tagNameItem.addActionListener((ActionEvent e) -> {
|
||||
addTag(tagName, NO_COMMENT);
|
||||
getAndAddTag(entry.getKey(), entry.getValue(), NO_COMMENT);
|
||||
});
|
||||
quickTagMenu.add(tagNameItem);
|
||||
}
|
||||
@ -143,5 +145,30 @@ abstract class AddTagAction extends AbstractAction implements Presenter.Popup {
|
||||
});
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,10 +1,10 @@
|
||||
GetTagNameDialog.tagNameField.text=
|
||||
GetTagNameDialog.cancelButton.text=Cancel
|
||||
GetTagNameDialog.okButton.text=OK
|
||||
GetTagNameDialog.preexistingLabel.text=Pre-existing Tags:
|
||||
GetTagNameDialog.preexistingLabel.text=Pre-existing Tag Names:
|
||||
GetTagNameDialog.newTagPanel.border.title=New Tag
|
||||
GetTagNameDialog.tagNameLabel.text=Tag Name:
|
||||
GetTagNameAndCommentDialog.newTagButton.text=New Tag
|
||||
GetTagNameAndCommentDialog.newTagButton.text=New Tag Name
|
||||
GetTagNameAndCommentDialog.okButton.text=OK
|
||||
GetTagNameAndCommentDialog.commentText.toolTipText=Enter an optional tag comment or leave blank
|
||||
GetTagNameAndCommentDialog.commentText.text=
|
||||
@ -42,7 +42,7 @@ GetTagNameDialog.createTag=Create Tag
|
||||
GetTagNameDialog.cancelName=Cancel
|
||||
GetTagNameDialog.mustSupplyTtagName.msg=Must supply a tag name to continue.
|
||||
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.unableToAddTagNameToCase.msg=Unable to add the {0} tag name to the case.
|
||||
GetTagNameDialog.taggingErr=Tagging Error
|
||||
|
@ -28,7 +28,7 @@
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<Group type="102" alignment="1" 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"/>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Component id="cancelButton" linkSize="1" min="-2" max="-2" attributes="0"/>
|
||||
|
@ -21,8 +21,8 @@ package org.sleuthkit.autopsy.actions;
|
||||
import java.awt.Window;
|
||||
import java.awt.event.ActionEvent;
|
||||
import java.awt.event.KeyEvent;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.TreeMap;
|
||||
import java.util.logging.Level;
|
||||
import javax.swing.AbstractAction;
|
||||
import javax.swing.ActionMap;
|
||||
@ -43,7 +43,7 @@ public class GetTagNameAndCommentDialog extends JDialog {
|
||||
private static final long serialVersionUID = 1L;
|
||||
private static final String NO_TAG_NAMES_MESSAGE = NbBundle.getMessage(GetTagNameAndCommentDialog.class,
|
||||
"GetTagNameAndCommentDialog.noTags");
|
||||
private final HashMap<String, TagName> tagNames = new HashMap<>();
|
||||
private final Map<String, TagName> tagNamesMap = new TreeMap<>();
|
||||
private TagNameAndComment tagNameAndComment = null;
|
||||
|
||||
public static class TagNameAndComment {
|
||||
@ -91,13 +91,18 @@ public class GetTagNameAndCommentDialog extends JDialog {
|
||||
* dialog.
|
||||
*/
|
||||
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) {
|
||||
super(owner,
|
||||
NbBundle.getMessage(GetTagNameAndCommentDialog.class, "GetTagNameAndCommentDialog.createTag"),
|
||||
ModalityType.APPLICATION_MODAL);
|
||||
}
|
||||
|
||||
private void display() {
|
||||
initComponents();
|
||||
|
||||
// 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);
|
||||
ActionMap actionMap = getRootPane().getActionMap();
|
||||
actionMap.put(cancelName, new AbstractAction() {
|
||||
private static final long serialVersionUID = 1L;
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
dispose();
|
||||
@ -114,24 +120,24 @@ public class GetTagNameAndCommentDialog extends JDialog {
|
||||
|
||||
// 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 may be null (user tag names that have not been used do
|
||||
// not exist in the database).
|
||||
TagsManager tagsManager = Case.getCurrentCase().getServices().getTagsManager();
|
||||
List<TagName> currentTagNames = null;
|
||||
try {
|
||||
currentTagNames = tagsManager.getAllTagNames();
|
||||
tagNamesMap.putAll(tagsManager.getDisplayNamesToTagNamesMap());
|
||||
} catch (TskCoreException ex) {
|
||||
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);
|
||||
} else {
|
||||
for (TagName tagName : currentTagNames) {
|
||||
tagNames.put(tagName.getDisplayName(), tagName);
|
||||
tagCombo.addItem(tagName.getDisplayName());
|
||||
for (String tagDisplayName : tagNamesMap.keySet()) {
|
||||
tagCombo.addItem(tagDisplayName);
|
||||
}
|
||||
}
|
||||
|
||||
// Center and show the dialog box.
|
||||
this.setLocationRelativeTo(WindowManager.getDefault().getMainWindow());
|
||||
this.setLocationRelativeTo(this.getOwner());
|
||||
setVisible(true);
|
||||
}
|
||||
|
||||
@ -197,7 +203,7 @@ public class GetTagNameAndCommentDialog extends JDialog {
|
||||
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
.addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
|
||||
.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)
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||
.addComponent(cancelButton))
|
||||
@ -240,7 +246,18 @@ public class GetTagNameAndCommentDialog extends JDialog {
|
||||
}// </editor-fold>//GEN-END:initComponents
|
||||
|
||||
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();
|
||||
}//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
|
||||
TagName newTagName = GetTagNameDialog.doDialog(this);
|
||||
if (newTagName != null) {
|
||||
tagNames.put(newTagName.getDisplayName(), newTagName);
|
||||
tagNamesMap.put(newTagName.getDisplayName(), newTagName);
|
||||
tagCombo.addItem(newTagName.getDisplayName());
|
||||
tagCombo.setSelectedItem(newTagName.getDisplayName());
|
||||
}
|
||||
|
@ -1,7 +1,7 @@
|
||||
/*
|
||||
* Autopsy Forensic Browser
|
||||
*
|
||||
* Copyright 2013 Basis Technology Corp.
|
||||
* Copyright 2011-2016 Basis Technology Corp.
|
||||
* Contact: carrier <at> sleuthkit <dot> org
|
||||
*
|
||||
* 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.KeyEvent;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.TreeMap;
|
||||
import java.util.logging.Level;
|
||||
import javax.swing.AbstractAction;
|
||||
import javax.swing.ActionMap;
|
||||
@ -44,8 +45,9 @@ import org.sleuthkit.datamodel.TskCoreException;
|
||||
|
||||
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 final HashMap<String, TagName> tagNames = new HashMap<>();
|
||||
private final Map<String, TagName> tagNamesMap = new TreeMap<>();
|
||||
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
|
||||
* canceled the dialog.
|
||||
*/
|
||||
public static TagName doDialog(final Window owner) {
|
||||
return new GetTagNameDialog(owner).tagName;
|
||||
public static TagName doDialog(Window owner) {
|
||||
GetTagNameDialog dialog = new GetTagNameDialog(owner);
|
||||
dialog.display();
|
||||
return dialog.tagName;
|
||||
}
|
||||
|
||||
private GetTagNameDialog(final Window owner) {
|
||||
private GetTagNameDialog(Window owner) {
|
||||
super(owner,
|
||||
NbBundle.getMessage(GetTagNameDialog.class, "GetTagNameDialog.createTag"),
|
||||
ModalityType.APPLICATION_MODAL);
|
||||
}
|
||||
|
||||
private void display() {
|
||||
setIconImage(ImageUtilities.loadImage(TAG_ICON_PATH));
|
||||
initComponents();
|
||||
|
||||
@ -87,6 +94,8 @@ public class GetTagNameDialog extends JDialog {
|
||||
inputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_ESCAPE, 0), cancelName);
|
||||
ActionMap actionMap = getRootPane().getActionMap();
|
||||
actionMap.put(cancelName, new AbstractAction() {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent 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
|
||||
// case the user chooses an existing tag name from the tag names table.
|
||||
TagsManager tagsManager = Case.getCurrentCase().getServices().getTagsManager();
|
||||
List<TagName> currentTagNames = null;
|
||||
try {
|
||||
currentTagNames = tagsManager.getAllTagNames();
|
||||
tagNamesMap.putAll(tagsManager.getDisplayNamesToTagNamesMap());
|
||||
} catch (TskCoreException ex) {
|
||||
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.
|
||||
tagsTable.setModel(new TagsTableModel(currentTagNames));
|
||||
tagsTable.setModel(new TagsTableModel(new ArrayList<>(tagNamesMap.keySet())));
|
||||
tagsTable.setTableHeader(null);
|
||||
tagsTable.setCellSelectionEnabled(false);
|
||||
tagsTable.setFocusable(false);
|
||||
tagsTable.setRowHeight(tagsTable.getRowHeight() + 5);
|
||||
|
||||
// Center and show the dialog box.
|
||||
this.setLocationRelativeTo(owner);
|
||||
this.setLocationRelativeTo(this.getOwner());
|
||||
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 final ArrayList<TagName> tagNames = new ArrayList<>();
|
||||
private static final long serialVersionUID = 1L;
|
||||
private final ArrayList<String> tagDisplayNames = new ArrayList<>();
|
||||
|
||||
TagsTableModel(List<TagName> tagNames) {
|
||||
for (TagName tagName : tagNames) {
|
||||
this.tagNames.add(tagName);
|
||||
TagsTableModel(List<String> tagDisplayNames) {
|
||||
for (String tagDisplayName : tagDisplayNames) {
|
||||
this.tagDisplayNames.add(tagDisplayName);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getRowCount() {
|
||||
return tagNames.size();
|
||||
return tagDisplayNames.size();
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -160,7 +151,7 @@ public class GetTagNameDialog extends JDialog {
|
||||
|
||||
@Override
|
||||
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"),
|
||||
NbBundle.getMessage(this.getClass(), "GetTagNameDialog.tagNameErr"),
|
||||
JOptionPane.ERROR_MESSAGE);
|
||||
} else if (containsIllegalCharacters(tagDisplayName)) {
|
||||
} else if (TagsManager.containsIllegalCharacters(tagDisplayName)) {
|
||||
JOptionPane.showMessageDialog(null,
|
||||
NbBundle.getMessage(this.getClass(), "GetTagNameDialog.illegalChars.msg"),
|
||||
NbBundle.getMessage(this.getClass(), "GetTagNameDialog.illegalCharsErr"),
|
||||
JOptionPane.ERROR_MESSAGE);
|
||||
} else {
|
||||
tagName = tagNames.get(tagDisplayName);
|
||||
tagName = tagNamesMap.get(tagDisplayName);
|
||||
if (tagName == null) {
|
||||
try {
|
||||
tagName = Case.getCurrentCase().getServices().getTagsManager().addTagName(tagDisplayName);
|
||||
@ -326,7 +317,7 @@ public class GetTagNameDialog extends JDialog {
|
||||
JOptionPane.ERROR_MESSAGE);
|
||||
tagName = null;
|
||||
} 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,
|
||||
NbBundle.getMessage(this.getClass(),
|
||||
"GetTagNameDialog.tagNameAlreadyDef.msg",
|
||||
|
@ -1,9 +1,18 @@
|
||||
TagsManager.addContentTag.exception.beginByteOffsetOOR.msg=beginByteOffset \= {0} out of content size range (0 - {1})
|
||||
TagsManager.addContentTag.exception.endByteOffsetOOR.msg=endByteOffset \= {0} out of content size range (0 - {1})
|
||||
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.
|
||||
OptionsCategory_Name_TagNamesOptions=Tags
|
||||
OptionsCategory_TagNames=TagNames
|
||||
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
|
||||
|
@ -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.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
|
@ -27,6 +27,7 @@ import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.logging.Level;
|
||||
import org.openide.util.NbBundle;
|
||||
import org.sleuthkit.autopsy.datamodel.VirtualDirectoryNode;
|
||||
import org.sleuthkit.autopsy.ingest.IngestServices;
|
||||
@ -43,6 +44,7 @@ import org.sleuthkit.datamodel.VirtualDirectory;
|
||||
import org.sleuthkit.datamodel.LocalFilesDataSource;
|
||||
import org.sleuthkit.datamodel.TskDataException;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.sleuthkit.autopsy.coreutils.Logger;
|
||||
import org.sleuthkit.datamodel.CarvingResult;
|
||||
import org.sleuthkit.datamodel.TskData;
|
||||
|
||||
@ -53,6 +55,7 @@ import org.sleuthkit.datamodel.TskData;
|
||||
*/
|
||||
public class FileManager implements Closeable {
|
||||
|
||||
private static final Logger LOGGER = Logger.getLogger(FileManager.class.getName());
|
||||
private SleuthkitCase caseDb;
|
||||
|
||||
/**
|
||||
@ -427,7 +430,11 @@ public class FileManager implements Closeable {
|
||||
|
||||
} catch (TskCoreException ex) {
|
||||
if (null != trans) {
|
||||
try {
|
||||
trans.rollback();
|
||||
} catch (TskCoreException ex2) {
|
||||
LOGGER.log(Level.SEVERE, String.format("Failed to rollback transaction after exception: %s", ex.getMessage()), ex2);
|
||||
}
|
||||
}
|
||||
throw ex;
|
||||
}
|
||||
|
98
Core/src/org/sleuthkit/autopsy/casemodule/services/NewTagNameDialog.form
Executable 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, "{key}")"/>
|
||||
</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, "{key}")"/>
|
||||
</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, "{key}")"/>
|
||||
</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, "{key}")"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
<Events>
|
||||
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="okButtonActionPerformed"/>
|
||||
</Events>
|
||||
</Component>
|
||||
</SubComponents>
|
||||
</Form>
|
247
Core/src/org/sleuthkit/autopsy/casemodule/services/NewTagNameDialog.java
Executable 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
|
||||
}
|
@ -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());
|
||||
}
|
||||
|
||||
}
|
204
Core/src/org/sleuthkit/autopsy/casemodule/services/TagOptionsPanel.form
Executable 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, "{key}")"/>
|
||||
</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, "{key}")"/>
|
||||
</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="<org.sleuthkit.autopsy.casemodule.services.TagNameDefiniton>"/>
|
||||
</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, "{key}")"/>
|
||||
</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, "{key}")"/>
|
||||
</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>
|
272
Core/src/org/sleuthkit/autopsy/casemodule/services/TagOptionsPanel.java
Executable 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);
|
||||
}
|
||||
|
||||
}
|
@ -22,12 +22,14 @@ import java.io.Closeable;
|
||||
import java.io.IOException;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.logging.Level;
|
||||
import org.openide.util.NbBundle;
|
||||
import org.sleuthkit.autopsy.casemodule.Case;
|
||||
import org.sleuthkit.autopsy.coreutils.Logger;
|
||||
import org.sleuthkit.autopsy.coreutils.ModuleSettings;
|
||||
import org.sleuthkit.datamodel.BlackboardArtifact;
|
||||
import org.sleuthkit.datamodel.BlackboardArtifactTag;
|
||||
import org.sleuthkit.datamodel.Content;
|
||||
@ -37,22 +39,19 @@ import org.sleuthkit.datamodel.TagName;
|
||||
import org.sleuthkit.datamodel.TskCoreException;
|
||||
|
||||
/**
|
||||
* A per case Autopsy service that manages the creation, updating, and deletion
|
||||
* of tags applied to content and blackboard artifacts by users.
|
||||
* A per case Autopsy service that manages the addition of content and artifact
|
||||
* tags to the case database.
|
||||
*/
|
||||
public class TagsManager implements Closeable {
|
||||
|
||||
private static final Logger logger = Logger.getLogger(TagsManager.class.getName());
|
||||
private static final String TAGS_SETTINGS_NAME = "Tags"; //NON-NLS
|
||||
private static final String TAG_NAMES_SETTING_KEY = "TagNames"; //NON-NLS
|
||||
private SleuthkitCase caseDb;
|
||||
private final HashMap<String, TagName> uniqueTagNames = new HashMap<>();
|
||||
private boolean tagNamesLoaded = false;
|
||||
private static final Logger LOGGER = Logger.getLogger(TagsManager.class.getName());
|
||||
@NbBundle.Messages("TagsManager.predefTagNames.bookmark.text=Bookmark")
|
||||
private static final Set<String> STANDARD_TAG_DISPLAY_NAMES = new HashSet<>(Arrays.asList(Bundle.TagsManager_predefTagNames_bookmark_text()));
|
||||
private final SleuthkitCase caseDb;
|
||||
|
||||
/**
|
||||
* Constructs a per case Autopsy service that manages the creation,
|
||||
* updating, and deletion of tags applied to content and blackboard
|
||||
* artifacts by users.
|
||||
* Constructs a per case Autopsy service that manages the addition of
|
||||
* content and artifact tags to 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
|
||||
* artifacts.
|
||||
* Gets a list of all tag names currently in the case database.
|
||||
*
|
||||
* @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
|
||||
* database.
|
||||
* @throws TskCoreException If there is an error querying the case database.
|
||||
*/
|
||||
public synchronized List<TagName> getAllTagNames() throws TskCoreException {
|
||||
if (null == caseDb) {
|
||||
throw new TskCoreException("Tags manager has been closed");
|
||||
}
|
||||
lazyLoadExistingTagNames();
|
||||
public List<TagName> getAllTagNames() throws TskCoreException {
|
||||
return caseDb.getAllTagNames();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a list of all tag names currently in use for tagging content or
|
||||
* artifacts.
|
||||
* Gets a list of all tag names currently in use in the case database for
|
||||
* 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
|
||||
* database.
|
||||
* @throws TskCoreException If there is an error querying the case database.
|
||||
*/
|
||||
public synchronized List<TagName> getTagNamesInUse() throws TskCoreException {
|
||||
if (null == caseDb) {
|
||||
throw new TskCoreException("Tags manager has been closed");
|
||||
}
|
||||
lazyLoadExistingTagNames();
|
||||
public List<TagName> getTagNamesInUse() throws TskCoreException {
|
||||
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) {
|
||||
lazyLoadExistingTagNames();
|
||||
return uniqueTagNames.containsKey(tagDisplayName);
|
||||
public synchronized Map<String, TagName> getDisplayNamesToTagNamesMap() throws TskCoreException {
|
||||
/**
|
||||
* 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
|
||||
* name.
|
||||
* @return A TagName representing the tag name database entry that can be
|
||||
* used to add instances of the tag type to the case database.
|
||||
*
|
||||
* @throws TagNameAlreadyExistsException If the tag name would be a
|
||||
* duplicate.
|
||||
* @throws TagNameAlreadyExistsException If the tag name already exists in
|
||||
* the case database.
|
||||
* @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 {
|
||||
if (null == caseDb) {
|
||||
throw new TskCoreException("Tags manager has been closed");
|
||||
}
|
||||
public synchronized TagName addTagName(String displayName) throws TagNameAlreadyExistsException, TskCoreException {
|
||||
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 description The description for the new tag name.
|
||||
* @param displayName The display name for the new tag type.
|
||||
* @param description The description for the new tag type.
|
||||
*
|
||||
* @return A TagName data transfer object (DTO) representing the new tag
|
||||
* name.
|
||||
* @return A TagName object that can be used to add instances of the tag
|
||||
* type to the case database.
|
||||
*
|
||||
* @throws TagNameAlreadyExistsException If the tag name would be a
|
||||
* duplicate.
|
||||
* @throws TagNameAlreadyExistsException If the tag name already exists in
|
||||
* the case database.
|
||||
* @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 {
|
||||
if (null == caseDb) {
|
||||
throw new TskCoreException("Tags manager has been closed");
|
||||
}
|
||||
public synchronized TagName addTagName(String displayName, String description) throws TagNameAlreadyExistsException, TskCoreException {
|
||||
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 description The description for the new tag name.
|
||||
* @param color The HTML color to associate with the new tag name.
|
||||
* @param displayName The display name for the new tag type.
|
||||
* @param description The description for the new tag type.
|
||||
* @param color The color to associate with the new tag type.
|
||||
*
|
||||
* @return A TagName data transfer object (DTO) representing the new tag
|
||||
* name.
|
||||
* @return A TagName object that can be used to add instances of the tag
|
||||
* type to the case database.
|
||||
*
|
||||
* @throws TagNameAlreadyExistsException If the tag name would be a
|
||||
* duplicate.
|
||||
* @throws TagNameAlreadyExistsException If the tag name already exists.
|
||||
* @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 {
|
||||
if (null == caseDb) {
|
||||
throw new TskCoreException("Tags manager has been closed");
|
||||
try {
|
||||
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);
|
||||
}
|
||||
lazyLoadExistingTagNames();
|
||||
if (uniqueTagNames.containsKey(displayName)) {
|
||||
return tagName;
|
||||
} catch (TskCoreException ex) {
|
||||
List<TagName> existingTagNames = caseDb.getAllTagNames();
|
||||
for (TagName tagName : existingTagNames) {
|
||||
if (tagName.getDisplayName().equals(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;
|
||||
}
|
||||
throw ex;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Tags a content object.
|
||||
*
|
||||
* @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
|
||||
* database.
|
||||
*/
|
||||
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);
|
||||
}
|
||||
|
||||
@ -207,18 +213,17 @@ public class TagsManager implements Closeable {
|
||||
* Tags a content object.
|
||||
*
|
||||
* @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.
|
||||
*
|
||||
* @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
|
||||
* database.
|
||||
*/
|
||||
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);
|
||||
}
|
||||
|
||||
@ -226,56 +231,25 @@ public class TagsManager implements Closeable {
|
||||
* Tags a content object or a section of a content object.
|
||||
*
|
||||
* @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 beginByteOffset Designates the beginning 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
|
||||
* range.
|
||||
* @throws TskCoreException If there is an error adding the tag to
|
||||
* the case 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 {
|
||||
if (null == caseDb) {
|
||||
throw new TskCoreException("Tags manager has been closed");
|
||||
}
|
||||
public ContentTag addContentTag(Content content, TagName tagName, String comment, long beginByteOffset, long endByteOffset) throws TskCoreException {
|
||||
ContentTag tag;
|
||||
synchronized (this) {
|
||||
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 {
|
||||
Case.getCurrentCase().notifyContentTagAdded(tag);
|
||||
} 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;
|
||||
}
|
||||
@ -289,18 +263,11 @@ public class TagsManager implements Closeable {
|
||||
* case database.
|
||||
*/
|
||||
public void deleteContentTag(ContentTag tag) throws TskCoreException {
|
||||
if (null == caseDb) {
|
||||
throw new TskCoreException("Tags manager has been closed");
|
||||
}
|
||||
synchronized (this) {
|
||||
lazyLoadExistingTagNames();
|
||||
caseDb.deleteContentTag(tag);
|
||||
}
|
||||
|
||||
try {
|
||||
Case.getCurrentCase().notifyContentTagDeleted(tag);
|
||||
} 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.
|
||||
*/
|
||||
public synchronized List<ContentTag> getAllContentTags() throws TskCoreException {
|
||||
if (null == caseDb) {
|
||||
throw new TskCoreException("Tags manager has been closed");
|
||||
}
|
||||
lazyLoadExistingTagNames();
|
||||
return caseDb.getAllContentTags();
|
||||
}
|
||||
|
||||
/**
|
||||
* 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.
|
||||
*
|
||||
@ -331,29 +296,21 @@ public class TagsManager implements Closeable {
|
||||
* the case database.
|
||||
*/
|
||||
public synchronized long getContentTagsCountByTagName(TagName tagName) throws TskCoreException {
|
||||
if (null == caseDb) {
|
||||
throw new TskCoreException("Tags manager has been closed");
|
||||
}
|
||||
lazyLoadExistingTagNames();
|
||||
return caseDb.getContentTagsCountByTagName(tagName);
|
||||
}
|
||||
|
||||
/**
|
||||
* 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.
|
||||
*
|
||||
* @throws TskCoreException If there is an error getting the tag from the
|
||||
* case database.
|
||||
*/
|
||||
public synchronized ContentTag getContentTagByTagID(long tagID) throws TskCoreException {
|
||||
if (null == caseDb) {
|
||||
throw new TskCoreException("Tags manager has been closed");
|
||||
}
|
||||
lazyLoadExistingTagNames();
|
||||
return caseDb.getContentTagByID(tagID);
|
||||
public synchronized ContentTag getContentTagByTagID(long tagId) throws TskCoreException {
|
||||
return caseDb.getContentTagByID(tagId);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -368,10 +325,6 @@ public class TagsManager implements Closeable {
|
||||
* case database.
|
||||
*/
|
||||
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);
|
||||
}
|
||||
|
||||
@ -381,172 +334,136 @@ public class TagsManager implements Closeable {
|
||||
* @param content The content of interest.
|
||||
*
|
||||
* @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
|
||||
* case database.
|
||||
*/
|
||||
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);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tags a blackboard artifact object.
|
||||
* Tags an artifact.
|
||||
*
|
||||
* @param artifact The blackboard artifact to tag.
|
||||
* @param tagName The name to use for the tag.
|
||||
* @param artifact The artifact to 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
|
||||
* the new tag.
|
||||
* @return A BlackboardArtifactTag object representing the new tag.
|
||||
*
|
||||
* @throws TskCoreException If there is an error adding the tag to the case
|
||||
* database.
|
||||
*/
|
||||
public BlackboardArtifactTag addBlackboardArtifactTag(BlackboardArtifact artifact, TagName tagName) throws TskCoreException {
|
||||
if (null == caseDb) {
|
||||
throw new TskCoreException("Tags manager has been closed");
|
||||
}
|
||||
public synchronized BlackboardArtifactTag addBlackboardArtifactTag(BlackboardArtifact artifact, TagName tagName) throws TskCoreException {
|
||||
return addBlackboardArtifactTag(artifact, tagName, "");
|
||||
}
|
||||
|
||||
/**
|
||||
* Tags a blackboard artifact object.
|
||||
* Tags an artifact.
|
||||
*
|
||||
* @param artifact The blackboard artifact to tag.
|
||||
* @param tagName The name to use for the tag.
|
||||
* @param artifact The artifact to 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.
|
||||
*
|
||||
* @return A BlackboardArtifactTag data transfer object (DTO) representing
|
||||
* the new tag.
|
||||
* @return A BlackboardArtifactTag object representing the new tag.
|
||||
*
|
||||
* @throws TskCoreException If there is an error adding the tag to the case
|
||||
* database.
|
||||
*/
|
||||
public BlackboardArtifactTag addBlackboardArtifactTag(BlackboardArtifact artifact, TagName tagName, String comment) throws TskCoreException {
|
||||
if (null == caseDb) {
|
||||
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);
|
||||
}
|
||||
|
||||
public synchronized BlackboardArtifactTag addBlackboardArtifactTag(BlackboardArtifact artifact, TagName tagName, String comment) throws TskCoreException {
|
||||
BlackboardArtifactTag tag = caseDb.addBlackboardArtifactTag(artifact, tagName, comment);
|
||||
try {
|
||||
Case.getCurrentCase().notifyBlackBoardArtifactTagAdded(tag);
|
||||
} 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;
|
||||
}
|
||||
|
||||
/**
|
||||
* Deletes a blackboard artifact tag.
|
||||
* Deletes an artifact tag.
|
||||
*
|
||||
* @param tag The tag to delete.
|
||||
*
|
||||
* @throws TskCoreException If there is an error deleting the tag from the
|
||||
* case database.
|
||||
*/
|
||||
public void deleteBlackboardArtifactTag(BlackboardArtifactTag tag) throws TskCoreException {
|
||||
if (null == caseDb) {
|
||||
throw new TskCoreException("Tags manager has been closed");
|
||||
}
|
||||
synchronized (this) {
|
||||
lazyLoadExistingTagNames();
|
||||
public synchronized void deleteBlackboardArtifactTag(BlackboardArtifactTag tag) throws TskCoreException {
|
||||
caseDb.deleteBlackboardArtifactTag(tag);
|
||||
}
|
||||
|
||||
try {
|
||||
Case.getCurrentCase().notifyBlackBoardArtifactTagDeleted(tag);
|
||||
} 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
|
||||
* case database.
|
||||
*/
|
||||
public synchronized List<BlackboardArtifactTag> getAllBlackboardArtifactTags() throws TskCoreException {
|
||||
if (null == caseDb) {
|
||||
throw new TskCoreException("Tags manager has been closed");
|
||||
}
|
||||
lazyLoadExistingTagNames();
|
||||
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
|
||||
* name.
|
||||
* @return A count of the artifact tags with the specified tag name.
|
||||
*
|
||||
* @throws TskCoreException If there is an error getting the tags count from
|
||||
* the case database.
|
||||
*/
|
||||
public synchronized long getBlackboardArtifactTagsCountByTagName(TagName tagName) throws TskCoreException {
|
||||
if (null == caseDb) {
|
||||
throw new TskCoreException("Tags manager has been closed");
|
||||
}
|
||||
lazyLoadExistingTagNames();
|
||||
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
|
||||
* case database.
|
||||
*/
|
||||
public synchronized BlackboardArtifactTag getBlackboardArtifactTagByTagID(long tagID) throws TskCoreException {
|
||||
if (null == caseDb) {
|
||||
throw new TskCoreException("Tags manager has been closed");
|
||||
}
|
||||
lazyLoadExistingTagNames();
|
||||
return caseDb.getBlackboardArtifactTagByID(tagID);
|
||||
public synchronized BlackboardArtifactTag getBlackboardArtifactTagByTagID(long tagId) throws TskCoreException {
|
||||
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
|
||||
* specified tag name.
|
||||
* @return A list, possibly empty, of the artifact tags with the specified
|
||||
* tag name.
|
||||
*
|
||||
* @throws TskCoreException If there is an error getting the tags from the
|
||||
* case database.
|
||||
*/
|
||||
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);
|
||||
}
|
||||
|
||||
/**
|
||||
* 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
|
||||
* artifact.
|
||||
@ -555,115 +472,29 @@ public class TagsManager implements Closeable {
|
||||
* case database.
|
||||
*/
|
||||
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);
|
||||
}
|
||||
|
||||
/**
|
||||
* Closes the tags manager, saving the avaialble tag names to secondary
|
||||
* storage.
|
||||
* Returns true if the tag display name contains an illegal character. Used
|
||||
* after a tag display name is retrieved from user input.
|
||||
*
|
||||
* @throws IOException If there is a problem closing the tags manager.
|
||||
* @deprecated Tags manager clients should not close the tags manager.
|
||||
* @param content Display name of the tag being added.
|
||||
*
|
||||
* @return boolean indicating whether the name has an invalid character.
|
||||
*/
|
||||
@Override
|
||||
@Deprecated
|
||||
public synchronized void close() throws IOException {
|
||||
saveTagNamesToTagsSettings();
|
||||
caseDb = null;
|
||||
}
|
||||
public static boolean containsIllegalCharacters(String content) {
|
||||
return (content.contains("\\")
|
||||
|| content.contains(":")
|
||||
|| content.contains("*")
|
||||
|| 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;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 {
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
BIN
Core/src/org/sleuthkit/autopsy/casemodule/services/tag-options-panel-icon.png
Executable file
After Width: | Height: | Size: 1.2 KiB |
@ -1,7 +1,7 @@
|
||||
/*
|
||||
* Autopsy Forensic Browser
|
||||
*
|
||||
* Copyright 2013 Basis Technology Corp.
|
||||
* Copyright 2011-2016 Basis Technology Corp.
|
||||
* Contact: carrier <at> sleuthkit <dot> org
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
@ -61,6 +61,7 @@ import org.sleuthkit.datamodel.TskCoreException;
|
||||
//@ServiceProvider(service = DataResultViewer.class)
|
||||
final class DataResultViewerThumbnail extends AbstractDataResultViewer {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
private static final Logger logger = Logger.getLogger(DataResultViewerThumbnail.class.getName());
|
||||
//flag to keep track if images are being loaded
|
||||
private int curPage;
|
||||
@ -95,7 +96,7 @@ final class DataResultViewerThumbnail extends AbstractDataResultViewer {
|
||||
|
||||
iconView.setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION);
|
||||
em.addPropertyChangeListener(new ExplorerManagerNodeSelectionListener());
|
||||
thumbnailSizeComboBox.setModel(new javax.swing.DefaultComboBoxModel<String>(
|
||||
thumbnailSizeComboBox.setModel(new javax.swing.DefaultComboBoxModel<>(
|
||||
new String[] { Bundle.DataResultViewerThumbnail_thumbnailSizeComboBox_small(),
|
||||
Bundle.DataResultViewerThumbnail_thumbnailSizeComboBox_medium(),
|
||||
Bundle.DataResultViewerThumbnail_thumbnailSizeComboBox_large() }));
|
||||
@ -395,11 +396,8 @@ final class DataResultViewerThumbnail extends AbstractDataResultViewer {
|
||||
|
||||
private void switchPage() {
|
||||
|
||||
EventQueue.invokeLater(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
EventQueue.invokeLater(() -> {
|
||||
setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
|
||||
}
|
||||
});
|
||||
|
||||
//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()),
|
||||
NotifyDescriptor.ERROR_MESSAGE);
|
||||
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 (java.util.concurrent.CancellationException ex) {
|
||||
}
|
||||
@ -453,6 +451,7 @@ final class DataResultViewerThumbnail extends AbstractDataResultViewer {
|
||||
goToPageField.setEnabled(false);
|
||||
pageNumLabel.setText("");
|
||||
imagesRangeLabel.setText("");
|
||||
thumbnailSizeComboBox.setEnabled(false);
|
||||
} else {
|
||||
pageNumLabel.setText(
|
||||
NbBundle.getMessage(this.getClass(), "DataResultViewerThumbnail.pageNumbers.curOfTotal",
|
||||
@ -464,7 +463,7 @@ final class DataResultViewerThumbnail extends AbstractDataResultViewer {
|
||||
pageNextButton.setEnabled(!(curPage == totalPages));
|
||||
pagePrevButton.setEnabled(!(curPage == 1));
|
||||
goToPageField.setEnabled(totalPages > 1);
|
||||
|
||||
thumbnailSizeComboBox.setEnabled(true);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -22,6 +22,12 @@ import org.openide.nodes.AbstractNode;
|
||||
import org.openide.nodes.Children.Keys;
|
||||
import org.openide.nodes.Node;
|
||||
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.DerivedFile;
|
||||
import org.sleuthkit.datamodel.Directory;
|
||||
|
@ -27,7 +27,6 @@ import org.openide.util.NbBundle;
|
||||
import org.sleuthkit.autopsy.coreutils.Logger;
|
||||
import org.sleuthkit.datamodel.BlackboardArtifact;
|
||||
import org.sleuthkit.datamodel.BlackboardAttribute;
|
||||
import org.sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE;
|
||||
import org.sleuthkit.datamodel.Content;
|
||||
import org.sleuthkit.datamodel.TskCoreException;
|
||||
import org.sleuthkit.datamodel.TskException;
|
||||
@ -78,22 +77,6 @@ public class ArtifactStringContent implements StringContent {
|
||||
|
||||
// value column
|
||||
buffer.append("<td>"); //NON-NLS
|
||||
if (attr.getAttributeType().getTypeID() == ATTRIBUTE_TYPE.TSK_DATETIME.getTypeID()
|
||||
|| attr.getAttributeType().getTypeID() == ATTRIBUTE_TYPE.TSK_DATETIME_ACCESSED.getTypeID()
|
||||
|| attr.getAttributeType().getTypeID() == ATTRIBUTE_TYPE.TSK_DATETIME_CREATED.getTypeID()
|
||||
|| attr.getAttributeType().getTypeID() == ATTRIBUTE_TYPE.TSK_DATETIME_MODIFIED.getTypeID()
|
||||
|| attr.getAttributeType().getTypeID() == ATTRIBUTE_TYPE.TSK_DATETIME_RCVD.getTypeID()
|
||||
|| attr.getAttributeType().getTypeID() == ATTRIBUTE_TYPE.TSK_DATETIME_SENT.getTypeID()
|
||||
|| attr.getAttributeType().getTypeID() == ATTRIBUTE_TYPE.TSK_DATETIME_START.getTypeID()
|
||||
|| attr.getAttributeType().getTypeID() == ATTRIBUTE_TYPE.TSK_DATETIME_END.getTypeID()) {
|
||||
long epoch = attr.getValueLong();
|
||||
String time = "0000-00-00 00:00:00";
|
||||
if (epoch != 0) {
|
||||
dateFormatter.setTimeZone(getTimeZone(artifact));
|
||||
time = dateFormatter.format(new java.util.Date(epoch * 1000));
|
||||
}
|
||||
buffer.append(time);
|
||||
} else {
|
||||
switch (attr.getAttributeType().getValueType()) {
|
||||
case STRING:
|
||||
String str = attr.getValueString();
|
||||
@ -116,10 +99,14 @@ public class ArtifactStringContent implements StringContent {
|
||||
buffer.append(Arrays.toString(attr.getValueBytes()));
|
||||
break;
|
||||
case DATETIME:
|
||||
buffer.append(attr.getValueLong());
|
||||
break;
|
||||
|
||||
long epoch = attr.getValueLong();
|
||||
String time = "0000-00-00 00:00:00";
|
||||
if (epoch != 0) {
|
||||
dateFormatter.setTimeZone(getTimeZone(artifact));
|
||||
time = dateFormatter.format(new java.util.Date(epoch * 1000));
|
||||
}
|
||||
buffer.append(time);
|
||||
break;
|
||||
}
|
||||
if (!"".equals(attr.getContext())) {
|
||||
buffer.append(" (");
|
||||
|
@ -185,13 +185,13 @@ public class BlackboardArtifactNode extends DisplayableItemNode {
|
||||
ss = Sheet.createPropertiesSet();
|
||||
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<>();
|
||||
fillPropertyMap(map, artifact);
|
||||
|
||||
ss.put(new NodeProperty<>(NbBundle.getMessage(this.getClass(), "BlackboardArtifactNode.createSheet.srcFile.name"),
|
||||
NbBundle.getMessage(this.getClass(), "BlackboardArtifactNode.createSheet.srcFile.displayName"),
|
||||
ss.put(new NodeProperty<>(NbBundle.getMessage(BlackboardArtifactNode.class, "BlackboardArtifactNode.createSheet.srcFile.name"),
|
||||
NbBundle.getMessage(BlackboardArtifactNode.class, "BlackboardArtifactNode.createSheet.srcFile.displayName"),
|
||||
NO_DESCR,
|
||||
this.getDisplayName()));
|
||||
|
||||
@ -222,13 +222,13 @@ public class BlackboardArtifactNode extends DisplayableItemNode {
|
||||
actualMimeType = ""; //NON-NLS
|
||||
}
|
||||
}
|
||||
ss.put(new NodeProperty<>(NbBundle.getMessage(this.getClass(), "BlackboardArtifactNode.createSheet.ext.name"),
|
||||
NbBundle.getMessage(this.getClass(), "BlackboardArtifactNode.createSheet.ext.displayName"),
|
||||
ss.put(new NodeProperty<>(NbBundle.getMessage(BlackboardArtifactNode.class, "BlackboardArtifactNode.createSheet.ext.name"),
|
||||
NbBundle.getMessage(BlackboardArtifactNode.class, "BlackboardArtifactNode.createSheet.ext.displayName"),
|
||||
NO_DESCR,
|
||||
ext));
|
||||
ss.put(new NodeProperty<>(
|
||||
NbBundle.getMessage(this.getClass(), "BlackboardArtifactNode.createSheet.mimeType.name"),
|
||||
NbBundle.getMessage(this.getClass(), "BlackboardArtifactNode.createSheet.mimeType.displayName"),
|
||||
NbBundle.getMessage(BlackboardArtifactNode.class, "BlackboardArtifactNode.createSheet.mimeType.name"),
|
||||
NbBundle.getMessage(BlackboardArtifactNode.class, "BlackboardArtifactNode.createSheet.mimeType.displayName"),
|
||||
NO_DESCR,
|
||||
actualMimeType));
|
||||
}
|
||||
@ -243,32 +243,32 @@ public class BlackboardArtifactNode extends DisplayableItemNode {
|
||||
|
||||
if (sourcePath.isEmpty() == false) {
|
||||
ss.put(new NodeProperty<>(
|
||||
NbBundle.getMessage(this.getClass(), "BlackboardArtifactNode.createSheet.filePath.name"),
|
||||
NbBundle.getMessage(this.getClass(), "BlackboardArtifactNode.createSheet.filePath.displayName"),
|
||||
NbBundle.getMessage(BlackboardArtifactNode.class, "BlackboardArtifactNode.createSheet.filePath.name"),
|
||||
NbBundle.getMessage(BlackboardArtifactNode.class, "BlackboardArtifactNode.createSheet.filePath.displayName"),
|
||||
NO_DESCR,
|
||||
sourcePath));
|
||||
}
|
||||
|
||||
if (Arrays.asList(SHOW_FILE_METADATA).contains(artifactTypeId)) {
|
||||
AbstractFile file = associated instanceof AbstractFile ? (AbstractFile) associated : null;
|
||||
ss.put(new NodeProperty<>(NbBundle.getMessage(this.getClass(), "ContentTagNode.createSheet.fileModifiedTime.name"),
|
||||
NbBundle.getMessage(this.getClass(), "ContentTagNode.createSheet.fileModifiedTime.displayName"),
|
||||
ss.put(new NodeProperty<>(NbBundle.getMessage(BlackboardArtifactNode.class, "ContentTagNode.createSheet.fileModifiedTime.name"),
|
||||
NbBundle.getMessage(BlackboardArtifactNode.class, "ContentTagNode.createSheet.fileModifiedTime.displayName"),
|
||||
"",
|
||||
file != null ? ContentUtils.getStringTime(file.getMtime(), file) : ""));
|
||||
ss.put(new NodeProperty<>(NbBundle.getMessage(this.getClass(), "ContentTagNode.createSheet.fileChangedTime.name"),
|
||||
NbBundle.getMessage(this.getClass(), "ContentTagNode.createSheet.fileChangedTime.displayName"),
|
||||
ss.put(new NodeProperty<>(NbBundle.getMessage(BlackboardArtifactNode.class, "ContentTagNode.createSheet.fileChangedTime.name"),
|
||||
NbBundle.getMessage(BlackboardArtifactNode.class, "ContentTagNode.createSheet.fileChangedTime.displayName"),
|
||||
"",
|
||||
file != null ? ContentUtils.getStringTime(file.getCtime(), file) : ""));
|
||||
ss.put(new NodeProperty<>(NbBundle.getMessage(this.getClass(), "ContentTagNode.createSheet.fileAccessedTime.name"),
|
||||
NbBundle.getMessage(this.getClass(), "ContentTagNode.createSheet.fileAccessedTime.displayName"),
|
||||
ss.put(new NodeProperty<>(NbBundle.getMessage(BlackboardArtifactNode.class, "ContentTagNode.createSheet.fileAccessedTime.name"),
|
||||
NbBundle.getMessage(BlackboardArtifactNode.class, "ContentTagNode.createSheet.fileAccessedTime.displayName"),
|
||||
"",
|
||||
file != null ? ContentUtils.getStringTime(file.getAtime(), file) : ""));
|
||||
ss.put(new NodeProperty<>(NbBundle.getMessage(this.getClass(), "ContentTagNode.createSheet.fileCreatedTime.name"),
|
||||
NbBundle.getMessage(this.getClass(), "ContentTagNode.createSheet.fileCreatedTime.displayName"),
|
||||
ss.put(new NodeProperty<>(NbBundle.getMessage(BlackboardArtifactNode.class, "ContentTagNode.createSheet.fileCreatedTime.name"),
|
||||
NbBundle.getMessage(BlackboardArtifactNode.class, "ContentTagNode.createSheet.fileCreatedTime.displayName"),
|
||||
"",
|
||||
file != null ? ContentUtils.getStringTime(file.getCrtime(), file) : ""));
|
||||
ss.put(new NodeProperty<>(NbBundle.getMessage(this.getClass(), "ContentTagNode.createSheet.fileSize.name"),
|
||||
NbBundle.getMessage(this.getClass(), "ContentTagNode.createSheet.fileSize.displayName"),
|
||||
ss.put(new NodeProperty<>(NbBundle.getMessage(BlackboardArtifactNode.class, "ContentTagNode.createSheet.fileSize.name"),
|
||||
NbBundle.getMessage(BlackboardArtifactNode.class, "ContentTagNode.createSheet.fileSize.displayName"),
|
||||
"",
|
||||
associated.getSize()));
|
||||
}
|
||||
@ -287,8 +287,8 @@ public class BlackboardArtifactNode extends DisplayableItemNode {
|
||||
|
||||
if (dataSourceStr.isEmpty() == false) {
|
||||
ss.put(new NodeProperty<>(
|
||||
NbBundle.getMessage(this.getClass(), "BlackboardArtifactNode.createSheet.dataSrc.name"),
|
||||
NbBundle.getMessage(this.getClass(), "BlackboardArtifactNode.createSheet.dataSrc.displayName"),
|
||||
NbBundle.getMessage(BlackboardArtifactNode.class, "BlackboardArtifactNode.createSheet.dataSrc.name"),
|
||||
NbBundle.getMessage(BlackboardArtifactNode.class, "BlackboardArtifactNode.createSheet.dataSrc.displayName"),
|
||||
NO_DESCR,
|
||||
dataSourceStr));
|
||||
}
|
||||
|
@ -118,17 +118,6 @@ FileSize.createSheet.filterType.displayName=Filter Type
|
||||
FileSize.createSheet.filterType.desc=no description
|
||||
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}
|
||||
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.displayName=Filter Type
|
||||
FileTypeNode.createSheet.filterType.desc=no description
|
||||
|
171
Core/src/org/sleuthkit/autopsy/datamodel/CreditCards.java
Normal 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);
|
||||
}
|
||||
}
|
@ -18,6 +18,9 @@
|
||||
*/
|
||||
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
|
||||
*/
|
||||
|
@ -18,6 +18,8 @@
|
||||
*/
|
||||
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.PropertyChangeListener;
|
||||
import java.util.ArrayList;
|
||||
|
@ -22,6 +22,7 @@ import org.sleuthkit.autopsy.datamodel.DeletedContent.DeletedContentsChildren.De
|
||||
import org.sleuthkit.autopsy.datamodel.DeletedContent.DeletedContentsNode;
|
||||
import org.sleuthkit.autopsy.datamodel.FileSize.FileSizeRootChildren.FileSizeNode;
|
||||
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
|
||||
@ -127,7 +128,7 @@ public interface DisplayableItemNodeVisitor<T> {
|
||||
*/
|
||||
T visit(Accounts.AccountsRootNode accountRootNode);
|
||||
|
||||
T visit(Accounts.AccountTypeNode accountTypeNode);
|
||||
T visit(Accounts.CreditCardNumberAccountTypeNode accountTypeNode);
|
||||
|
||||
T visit(Accounts.ByBINNode byArtifactNode);
|
||||
|
||||
@ -137,6 +138,8 @@ public interface DisplayableItemNodeVisitor<T> {
|
||||
|
||||
T visit(Accounts.BINNode binNode);
|
||||
|
||||
T visit(Accounts.DefaultAccountTypeNode node);
|
||||
|
||||
/**
|
||||
* Visitor with an implementable default behavior for all types. Override
|
||||
* specific visit types to not use the default behavior.
|
||||
@ -350,7 +353,7 @@ public interface DisplayableItemNodeVisitor<T> {
|
||||
}
|
||||
|
||||
@Override
|
||||
public T visit(Accounts.AccountTypeNode node) {
|
||||
public T visit(Accounts.CreditCardNumberAccountTypeNode node) {
|
||||
return defaultVisit(node);
|
||||
}
|
||||
|
||||
@ -378,5 +381,9 @@ public interface DisplayableItemNodeVisitor<T> {
|
||||
public T visit(Accounts.BINNode node) {
|
||||
return defaultVisit(node);
|
||||
}
|
||||
@Override
|
||||
public T visit(Accounts.DefaultAccountTypeNode node) {
|
||||
return defaultVisit(node);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -18,6 +18,8 @@
|
||||
*/
|
||||
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.PropertyChangeListener;
|
||||
import java.sql.ResultSet;
|
||||
|
@ -18,6 +18,8 @@
|
||||
*/
|
||||
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.PropertyChangeListener;
|
||||
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.ModuleDataEvent;
|
||||
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_GEN_INFO;
|
||||
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_INTERESTING_FILE_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) -> {
|
||||
|
@ -18,6 +18,8 @@
|
||||
*/
|
||||
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.PropertyChangeListener;
|
||||
import java.util.ArrayList;
|
||||
|
@ -18,6 +18,7 @@
|
||||
*/
|
||||
package org.sleuthkit.autopsy.datamodel;
|
||||
|
||||
import org.sleuthkit.autopsy.datamodel._private.FileTypeExtensionFilters;
|
||||
import java.util.List;
|
||||
import java.util.Observable;
|
||||
import java.util.Observer;
|
||||
|
@ -18,6 +18,7 @@
|
||||
*/
|
||||
package org.sleuthkit.autopsy.datamodel;
|
||||
|
||||
import org.sleuthkit.autopsy.datamodel._private.FileTypeExtensionFilters;
|
||||
import java.beans.PropertyChangeEvent;
|
||||
import java.beans.PropertyChangeListener;
|
||||
import java.util.Arrays;
|
||||
|
@ -18,6 +18,8 @@
|
||||
*/
|
||||
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.PropertyChangeListener;
|
||||
import java.sql.ResultSet;
|
||||
|
@ -18,6 +18,8 @@
|
||||
*/
|
||||
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.PropertyChangeListener;
|
||||
import java.sql.ResultSet;
|
||||
|
@ -18,6 +18,8 @@
|
||||
*/
|
||||
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.PropertyChangeListener;
|
||||
import java.sql.ResultSet;
|
||||
|
@ -18,6 +18,7 @@
|
||||
*/
|
||||
package org.sleuthkit.autopsy.datamodel;
|
||||
|
||||
import org.sleuthkit.autopsy.datamodel._private.RecentFiles;
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
import java.util.Arrays;
|
||||
|
@ -28,7 +28,7 @@ import org.sleuthkit.autopsy.coreutils.Logger;
|
||||
import org.openide.nodes.AbstractNode;
|
||||
import org.openide.nodes.ChildFactory;
|
||||
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.Content;
|
||||
import org.sleuthkit.datamodel.ContentVisitor;
|
||||
|
@ -25,7 +25,7 @@ import org.sleuthkit.autopsy.coreutils.Logger;
|
||||
import org.openide.nodes.Children;
|
||||
import org.openide.nodes.Sheet;
|
||||
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;
|
||||
|
||||
/**
|
||||
|
@ -18,6 +18,8 @@
|
||||
*/
|
||||
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.event.ActionEvent;
|
||||
import java.beans.PropertyChangeEvent;
|
||||
|
@ -18,6 +18,8 @@
|
||||
*/
|
||||
package org.sleuthkit.autopsy.datamodel;
|
||||
|
||||
import org.sleuthkit.autopsy.datamodel._private.AutopsyItemVisitor;
|
||||
import org.sleuthkit.autopsy.datamodel._private.AutopsyVisitableItem;
|
||||
import org.sleuthkit.datamodel.SleuthkitCase;
|
||||
|
||||
/**
|
||||
|
@ -18,6 +18,7 @@
|
||||
*/
|
||||
package org.sleuthkit.autopsy.datamodel;
|
||||
|
||||
import org.sleuthkit.autopsy.datamodel._private.Accounts;
|
||||
import java.util.Arrays;
|
||||
import org.openide.nodes.Sheet;
|
||||
import org.openide.util.NbBundle;
|
||||
|
@ -18,6 +18,8 @@
|
||||
*/
|
||||
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.PropertyChangeListener;
|
||||
import java.util.Collections;
|
||||
|
@ -18,6 +18,8 @@
|
||||
*/
|
||||
package org.sleuthkit.autopsy.datamodel;
|
||||
|
||||
import org.sleuthkit.autopsy.datamodel._private.AutopsyItemVisitor;
|
||||
import org.sleuthkit.autopsy.datamodel._private.AutopsyVisitableItem;
|
||||
import org.sleuthkit.datamodel.SleuthkitCase;
|
||||
|
||||
/**
|
||||
|
@ -18,6 +18,7 @@
|
||||
*/
|
||||
package org.sleuthkit.autopsy.datamodel;
|
||||
|
||||
import org.sleuthkit.autopsy.datamodel._private.FileTypeExtensionFilters;
|
||||
import java.util.Arrays;
|
||||
import org.openide.nodes.Sheet;
|
||||
import org.openide.util.NbBundle;
|
||||
|
1368
Core/src/org/sleuthkit/autopsy/datamodel/_private/Accounts.java
Normal file
@ -16,14 +16,27 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* 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
|
||||
* nodes in the tree that are structural and not nodes that are from
|
||||
* Sleuthkit-based data model objects.
|
||||
*/
|
||||
interface AutopsyItemVisitor<T> {
|
||||
public interface AutopsyItemVisitor<T> {
|
||||
|
||||
T visit(DataSources i);
|
||||
|
@ -16,13 +16,14 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* 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
|
||||
* structure only. They are not associated with content objects.
|
||||
*/
|
||||
interface AutopsyVisitableItem {
|
||||
public interface AutopsyVisitableItem {
|
||||
|
||||
/**
|
||||
* visitor pattern support
|
146
Core/src/org/sleuthkit/autopsy/datamodel/_private/BINRange.java
Normal 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);
|
||||
}
|
||||
}
|
@ -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
|
||||
|
@ -16,20 +16,20 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.sleuthkit.autopsy.datamodel;
|
||||
package org.sleuthkit.autopsy.datamodel._private;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
import org.openide.util.NbBundle;
|
||||
import org.sleuthkit.autopsy.datamodel.FileTypeExtensions;
|
||||
import org.sleuthkit.datamodel.SleuthkitCase;
|
||||
|
||||
/**
|
||||
* 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
|
||||
public enum RootFilter implements AutopsyVisitableItem, SearchFilterInterface {
|
||||
@ -53,10 +53,10 @@ class FileTypeExtensionFilters implements AutopsyVisitableItem {
|
||||
NbBundle.getMessage(FileTypeExtensionFilters.class, "FileTypeExtensionFilters.tskExecFilter.text"),
|
||||
Arrays.asList(".exe", ".dll", ".bat", ".cmd", ".com")); //NON-NLS
|
||||
|
||||
private int id;
|
||||
private String name;
|
||||
private String displayName;
|
||||
private List<String> filter;
|
||||
private final int id;
|
||||
private final String name;
|
||||
private final String displayName;
|
||||
private final List<String> filter;
|
||||
|
||||
private RootFilter(int id, String name, String displayName, List<String> filter) {
|
||||
this.id = id;
|
||||
@ -110,10 +110,10 @@ class FileTypeExtensionFilters implements AutopsyVisitableItem {
|
||||
NbBundle.getMessage(FileTypeExtensionFilters.class, "FileTypeExtensionFilters.autDocRtfFilter.text"),
|
||||
Arrays.asList(".rtf")); //NON-NLS
|
||||
|
||||
private int id;
|
||||
private String name;
|
||||
private String displayName;
|
||||
private List<String> filter;
|
||||
private final int id;
|
||||
private final String name;
|
||||
private final String displayName;
|
||||
private final List<String> filter;
|
||||
|
||||
private DocumentFilter(int id, String name, String displayName, List<String> filter) {
|
||||
this.id = id;
|
||||
@ -157,10 +157,10 @@ class FileTypeExtensionFilters implements AutopsyVisitableItem {
|
||||
ExecutableFilter_CMD(3, "ExecutableFilter_CMD", ".cmd", Arrays.asList(".cmd")), //NON-NLS
|
||||
ExecutableFilter_COM(4, "ExecutableFilter_COM", ".com", Arrays.asList(".com")); //NON-NLS
|
||||
|
||||
private int id;
|
||||
private String name;
|
||||
private String displayName;
|
||||
private List<String> filter;
|
||||
private final int id;
|
||||
private final String name;
|
||||
private final String displayName;
|
||||
private final List<String> filter;
|
||||
|
||||
private ExecutableFilter(int id, String name, String displayName, List<String> filter) {
|
||||
this.id = id;
|
||||
@ -208,7 +208,7 @@ class FileTypeExtensionFilters implements AutopsyVisitableItem {
|
||||
return this.skCase;
|
||||
}
|
||||
|
||||
interface SearchFilterInterface {
|
||||
public interface SearchFilterInterface {
|
||||
|
||||
public String getName();
|
||||
|
@ -16,7 +16,7 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.sleuthkit.autopsy.datamodel;
|
||||
package org.sleuthkit.autopsy.datamodel._private;
|
||||
|
||||
import org.openide.util.NbBundle;
|
||||
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
|
||||
* 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;
|
||||
|
@ -37,38 +37,15 @@ import org.sleuthkit.autopsy.coreutils.ContextMenuExtensionPoint;
|
||||
import org.sleuthkit.autopsy.coreutils.Logger;
|
||||
import org.sleuthkit.autopsy.datamodel.AbstractAbstractFileNode.AbstractFilePropertyType;
|
||||
import org.sleuthkit.autopsy.datamodel.AbstractFsContentNode;
|
||||
import org.sleuthkit.autopsy.datamodel.Accounts;
|
||||
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.DisplayableItemNode;
|
||||
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.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.LocalFileNode;
|
||||
import org.sleuthkit.autopsy.datamodel.RecentFilesFilterNode;
|
||||
import org.sleuthkit.autopsy.datamodel.RecentFilesNode;
|
||||
import org.sleuthkit.autopsy.datamodel.Reports;
|
||||
import org.sleuthkit.autopsy.datamodel.Tags;
|
||||
import org.sleuthkit.autopsy.datamodel.VirtualDirectoryNode;
|
||||
import org.sleuthkit.autopsy.datamodel.VolumeNode;
|
||||
import org.sleuthkit.datamodel.AbstractFile;
|
||||
import org.sleuthkit.datamodel.BlackboardArtifact;
|
||||
import org.sleuthkit.datamodel.BlackboardAttribute;
|
||||
@ -301,112 +278,12 @@ public class DataResultFilterNode extends FilterNode {
|
||||
*/
|
||||
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
|
||||
public AbstractAction visit(BlackboardArtifactNode ban) {
|
||||
return new ViewContextAction(
|
||||
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
|
||||
public AbstractAction visit(DirectoryNode dn) {
|
||||
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
|
||||
public AbstractAction visit(FileNode fn) {
|
||||
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
|
||||
public AbstractAction visit(Reports.ReportNode reportNode) {
|
||||
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
|
||||
protected AbstractAction defaultVisit(DisplayableItemNode c) {
|
||||
return null;
|
||||
return openChild(c);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -57,7 +57,6 @@ import org.sleuthkit.autopsy.corecomponents.DataResultTopComponent;
|
||||
import org.sleuthkit.autopsy.corecomponents.TableFilterNode;
|
||||
import org.sleuthkit.autopsy.coreutils.Logger;
|
||||
import org.sleuthkit.autopsy.coreutils.MessageNotifyUtil;
|
||||
import org.sleuthkit.autopsy.datamodel.Accounts;
|
||||
import org.sleuthkit.autopsy.datamodel.BlackboardArtifactNode;
|
||||
import org.sleuthkit.autopsy.datamodel.DataSources;
|
||||
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.Views;
|
||||
import org.sleuthkit.autopsy.datamodel.ViewsNode;
|
||||
import org.sleuthkit.autopsy.datamodel._private.Accounts;
|
||||
import org.sleuthkit.autopsy.ingest.IngestManager;
|
||||
import org.sleuthkit.datamodel.BlackboardArtifact;
|
||||
import org.sleuthkit.datamodel.BlackboardAttribute;
|
||||
|
@ -40,7 +40,7 @@ public class ExternalViewerAction extends AbstractAction {
|
||||
|
||||
private final static Logger logger = Logger.getLogger(ExternalViewerAction.class.getName());
|
||||
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) {
|
||||
super(title);
|
||||
|
Before Width: | Height: | Size: 1.4 KiB After Width: | Height: | Size: 1.4 KiB |
BIN
Core/src/org/sleuthkit/autopsy/images/add-tag.png
Executable file
After Width: | Height: | Size: 1.6 KiB |
BIN
Core/src/org/sleuthkit/autopsy/images/delete-tag.png
Executable file
After Width: | Height: | Size: 1.7 KiB |
BIN
Core/src/org/sleuthkit/autopsy/images/edit-tag.png
Executable file
After Width: | Height: | Size: 1.7 KiB |
@ -254,8 +254,8 @@ class ReportHTML implements TableReportModule {
|
||||
case TSK_REMOTE_DRIVE:
|
||||
in = getClass().getResourceAsStream("/org/sleuthkit/autopsy/report/images/drive_network.png"); //NON-NLS
|
||||
break;
|
||||
case TSK_CREDIT_CARD_ACCOUNT:
|
||||
in = getClass().getResourceAsStream("/org/sleuthkit/autopsy/report/images/credit-card.png"); //NON-NLS
|
||||
case TSK_ACCOUNT:
|
||||
in = getClass().getResourceAsStream("/org/sleuthkit/autopsy/report/images/accounts.png"); //NON-NLS
|
||||
break;
|
||||
default:
|
||||
logger.log(Level.WARNING, "useDataTypeIcon: unhandled artifact type = " + dataType); //NON-NLS
|
||||
@ -264,6 +264,16 @@ class ReportHTML implements TableReportModule {
|
||||
iconFilePath = path + File.separator + iconFileName;
|
||||
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
|
||||
in = getClass().getResourceAsStream("/org/sleuthkit/autopsy/report/images/star.png"); //NON-NLS
|
||||
iconFileName = "star.png"; //NON-NLS
|
||||
|
@ -18,12 +18,16 @@
|
||||
*/
|
||||
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.SQLException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Iterator;
|
||||
@ -43,6 +47,7 @@ import org.sleuthkit.datamodel.AbstractFile;
|
||||
import org.sleuthkit.datamodel.BlackboardArtifact;
|
||||
import org.sleuthkit.datamodel.BlackboardArtifactTag;
|
||||
import org.sleuthkit.datamodel.BlackboardAttribute;
|
||||
import org.sleuthkit.datamodel.BlackboardAttribute.Type;
|
||||
import org.sleuthkit.datamodel.Content;
|
||||
import org.sleuthkit.datamodel.ContentTag;
|
||||
import org.sleuthkit.datamodel.SleuthkitCase;
|
||||
@ -119,10 +124,10 @@ class TableReportGenerator {
|
||||
*/
|
||||
private void makeBlackboardArtifactTables() {
|
||||
// Make a comment string describing the tag names filter in effect.
|
||||
StringBuilder comment = new StringBuilder();
|
||||
String comment = "";
|
||||
if (!tagNamesFilter.isEmpty()) {
|
||||
comment.append(NbBundle.getMessage(this.getClass(), "ReportGenerator.artifactTable.taggedResults.text"));
|
||||
comment.append(makeCommaSeparatedList(tagNamesFilter));
|
||||
comment += NbBundle.getMessage(this.getClass(), "ReportGenerator.artifactTable.taggedResults.text");
|
||||
comment += makeCommaSeparatedList(tagNamesFilter);
|
||||
}
|
||||
|
||||
// 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.
|
||||
if (type.getTypeID() == BlackboardArtifact.ARTIFACT_TYPE.TSK_KEYWORD_HIT.getTypeID()) {
|
||||
writeKeywordHits(tableReport, comment.toString(), tagNamesFilter);
|
||||
writeKeywordHits(tableReport, comment, tagNamesFilter);
|
||||
continue;
|
||||
} else if (type.getTypeID() == BlackboardArtifact.ARTIFACT_TYPE.TSK_HASHSET_HIT.getTypeID()) {
|
||||
writeHashsetHits(tableReport, comment.toString(), tagNamesFilter);
|
||||
writeHashsetHits(tableReport, comment, tagNamesFilter);
|
||||
continue;
|
||||
}
|
||||
|
||||
@ -152,43 +157,82 @@ class TableReportGenerator {
|
||||
continue;
|
||||
}
|
||||
|
||||
/*
|
||||
Gets all of the attribute types of this artifact type by adding
|
||||
all of the types to a set
|
||||
/* TSK_ACCOUNT artifacts get grouped by their TSK_ACCOUNT_TYPE
|
||||
* attribute, and then handed off to the standard method for writing
|
||||
* tables. */
|
||||
if (type.getTypeID() == BlackboardArtifact.ARTIFACT_TYPE.TSK_ACCOUNT.getTypeID()) {
|
||||
//Group account artifacts by their account type
|
||||
ListMultimap<String, ArtifactData> groupedArtifacts = Multimaps.index(artifactList,
|
||||
artifactData -> {
|
||||
try {
|
||||
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.
|
||||
*/
|
||||
Set<BlackboardAttribute.Type> attrTypeSet = new TreeSet<>((BlackboardAttribute.Type o1, BlackboardAttribute.Type o2) -> o1.getDisplayName().compareTo(o2.getDisplayName()));
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* 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.
|
||||
/* 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;
|
||||
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.
|
||||
/* 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);
|
||||
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()) {
|
||||
continue;
|
||||
return;
|
||||
}
|
||||
|
||||
tableReport.addRow(rowData);
|
||||
@ -198,7 +242,6 @@ class TableReportGenerator {
|
||||
tableReport.endTable();
|
||||
tableReport.endDataType();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Make table for tagged files
|
||||
@ -1449,8 +1492,9 @@ class TableReportGenerator {
|
||||
|
||||
columns.add(new AttributeColumn(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.remotePath"),
|
||||
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());
|
||||
attributeTypeSet.remove(new Type(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_ACCOUNT_TYPE));
|
||||
} else {
|
||||
// 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
|
||||
@ -1584,6 +1628,7 @@ class TableReportGenerator {
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private class AttributeColumn implements Column {
|
||||
|
||||
private final String columnHeader;
|
||||
@ -1643,10 +1688,6 @@ class TableReportGenerator {
|
||||
@Override
|
||||
public String getCellData(ArtifactData artData) {
|
||||
return getFileUniquePath(artData.getContent());
|
||||
/*else if (this.columnHeader.equals(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.tags"))) {
|
||||
return makeCommaSeparatedList(artData.getTags());
|
||||
}
|
||||
return "";*/
|
||||
}
|
||||
|
||||
@Override
|
||||
|
BIN
Core/src/org/sleuthkit/autopsy/report/images/account_menu.png
Normal file
After Width: | Height: | Size: 1.4 KiB |
@ -37,7 +37,7 @@ import org.sleuthkit.autopsy.casemodule.Case;
|
||||
import org.sleuthkit.autopsy.corecomponentinterfaces.DataContentViewer;
|
||||
import org.sleuthkit.autopsy.coreutils.Logger;
|
||||
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 org.sleuthkit.datamodel.BlackboardAttribute;
|
||||
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.
|
||||
Collection<? extends BlackboardArtifact> artifacts = nodeLookup.lookupAll(BlackboardArtifact.class);
|
||||
artifacts = (artifacts == null || artifacts.isEmpty())
|
||||
? content.getArtifacts(TSK_CREDIT_CARD_ACCOUNT)
|
||||
? content.getArtifacts(TSK_ACCOUNT)
|
||||
: artifacts;
|
||||
|
||||
/*
|
||||
@ -140,7 +140,7 @@ public class ExtractedContentViewer implements DataContentViewer {
|
||||
*/
|
||||
for (BlackboardArtifact artifact : artifacts) {
|
||||
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) {
|
||||
String valueString = solrIDAttr.getValueString();
|
||||
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) {
|
||||
String valueString = keyWordAttr.getValueString();
|
||||
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,
|
||||
* 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 {
|
||||
BlackboardAttribute attribute = artifact.getAttribute(TSK_ASSOCIATED_ARTIFACT_TYPE);
|
||||
if (attribute != null) {
|
||||
@ -296,7 +296,7 @@ public class ExtractedContentViewer implements DataContentViewer {
|
||||
Collection<? extends BlackboardArtifact> artifacts = node.getLookup().lookupAll(BlackboardArtifact.class);
|
||||
if (artifacts != null) {
|
||||
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;
|
||||
}
|
||||
}
|
||||
@ -321,7 +321,7 @@ public class ExtractedContentViewer implements DataContentViewer {
|
||||
if (art == null) {
|
||||
return 4;
|
||||
} 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;
|
||||
} else {
|
||||
return 4;
|
||||
|
@ -122,7 +122,7 @@ abstract class KeywordSearchList {
|
||||
|
||||
//CCN
|
||||
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");
|
||||
addList("Credit Card Numbers", ccns, true, false, true);
|
||||
}
|
||||
|
@ -34,8 +34,9 @@ import org.apache.solr.client.solrj.SolrQuery;
|
||||
import org.apache.solr.client.solrj.response.TermsResponse.Term;
|
||||
import org.sleuthkit.autopsy.coreutils.Logger;
|
||||
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.Account;
|
||||
import org.sleuthkit.datamodel.BlackboardArtifact;
|
||||
import org.sleuthkit.datamodel.BlackboardArtifact.ARTIFACT_TYPE;
|
||||
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 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 ACCOUNT_NUMBER_TYPE = new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_ACCOUNT_NUMBER);
|
||||
private static final BlackboardAttribute.Type KEYWORD_SEARCH_DOCUMENT_ID = new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_KEYWORD_SEARCH_DOCUMENT_ID);
|
||||
|
||||
//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<>();
|
||||
try {
|
||||
//if the keyword hit matched the credit card number keyword/regex...
|
||||
if (keyword.getType() == ATTRIBUTE_TYPE.TSK_ACCOUNT_NUMBER) {
|
||||
newArtifact = hit.getContent().newArtifact(ARTIFACT_TYPE.TSK_CREDIT_CARD_ACCOUNT);
|
||||
if (keyword.getType() == ATTRIBUTE_TYPE.TSK_CARD_NUMBER) {
|
||||
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
|
||||
//try to match it against the track 1 regex
|
||||
Matcher matcher = TRACK1_PATTERN.matcher(hit.getSnippet());
|
||||
@ -204,31 +209,31 @@ final class TermComponentQuery implements KeywordSearchQuery {
|
||||
AbstractFile file = (AbstractFile) hit.getContent();
|
||||
if (file.getType() == TskData.TSK_DB_FILES_TYPE_ENUM.UNUSED_BLOCKS
|
||||
|| file.getType() == TskData.TSK_DB_FILES_TYPE_ENUM.UNALLOC_BLOCKS) {
|
||||
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();
|
||||
final int iin = Integer.parseInt(ccn.substring(0, 8));
|
||||
String ccn = newArtifact.getAttribute(new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_CARD_NUMBER)).getValueString();
|
||||
final int bin = Integer.parseInt(ccn.substring(0, 8));
|
||||
|
||||
Accounts.IINInfo iinInfo = Accounts.getIINInfo(iin);
|
||||
CreditCards.BankIdentificationNumber binInfo = CreditCards.getBINInfo(bin);
|
||||
|
||||
if (iinInfo != null) {
|
||||
iinInfo.getScheme().ifPresent(scheme
|
||||
-> addAttributeSafe(newArtifact, ATTRIBUTE_TYPE.TSK_CREDIT_CARD_SCHEME, scheme));
|
||||
iinInfo.getCardType().ifPresent(cardType
|
||||
-> addAttributeSafe(newArtifact, ATTRIBUTE_TYPE.TSK_PAYMENT_CARD_TYPE, cardType));
|
||||
iinInfo.getBrand().ifPresent(brand
|
||||
-> addAttributeSafe(newArtifact, ATTRIBUTE_TYPE.TSK_BRAND, brand));
|
||||
iinInfo.getBankName().ifPresent(bankName
|
||||
if (binInfo != null) {
|
||||
binInfo.getScheme().ifPresent(scheme
|
||||
-> addAttributeSafe(newArtifact, ATTRIBUTE_TYPE.TSK_CARD_SCHEME, scheme));
|
||||
binInfo.getCardType().ifPresent(cardType
|
||||
-> addAttributeSafe(newArtifact, ATTRIBUTE_TYPE.TSK_CARD_TYPE, cardType));
|
||||
binInfo.getBrand().ifPresent(brand
|
||||
-> addAttributeSafe(newArtifact, ATTRIBUTE_TYPE.TSK_BRAND_NAME, brand));
|
||||
binInfo.getBankName().ifPresent(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));
|
||||
iinInfo.getBankURL().ifPresent(url
|
||||
binInfo.getBankURL().ifPresent(url
|
||||
-> addAttributeSafe(newArtifact, ATTRIBUTE_TYPE.TSK_URL, url));
|
||||
iinInfo.getCountry().ifPresent(country
|
||||
binInfo.getCountry().ifPresent(country
|
||||
-> addAttributeSafe(newArtifact, ATTRIBUTE_TYPE.TSK_COUNTRY, country));
|
||||
iinInfo.getBankCity().ifPresent(city
|
||||
binInfo.getBankCity().ifPresent(city
|
||||
-> addAttributeSafe(newArtifact, ATTRIBUTE_TYPE.TSK_CITY, city));
|
||||
}
|
||||
} else {
|
||||
@ -323,7 +328,7 @@ final class TermComponentQuery implements KeywordSearchQuery {
|
||||
for (Term term : terms) {
|
||||
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
|
||||
Matcher matcher = CCN_PATTERN.matcher(term.getTerm());
|
||||
matcher.find();
|
||||
@ -383,7 +388,7 @@ final class TermComponentQuery implements KeywordSearchQuery {
|
||||
BlackboardAttribute.Type type = new BlackboardAttribute.Type(attrType);
|
||||
if (artifact.getAttribute(type) == null) {
|
||||
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);
|
||||
}
|
||||
if (StringUtils.isNotBlank(value)) {
|
||||
@ -404,11 +409,11 @@ final class TermComponentQuery implements KeywordSearchQuery {
|
||||
*/
|
||||
static private void parseTrack2Data(BlackboardArtifact artifact, Matcher matcher) throws IllegalArgumentException, TskCoreException {
|
||||
//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_CREDIT_CARD_EXPIRATION, "expiration", matcher);
|
||||
addAttributeIfNotAlreadyCaptured(artifact, ATTRIBUTE_TYPE.TSK_CREDIT_CARD_SERVICE_CODE, "serviceCode", matcher);
|
||||
addAttributeIfNotAlreadyCaptured(artifact, ATTRIBUTE_TYPE.TSK_CREDIT_CARD_DISCRETIONARY, "discretionary", matcher);
|
||||
addAttributeIfNotAlreadyCaptured(artifact, ATTRIBUTE_TYPE.TSK_CREDIT_CARD_LRC, "LRC", matcher);
|
||||
addAttributeIfNotAlreadyCaptured(artifact, ATTRIBUTE_TYPE.TSK_CARD_NUMBER, "accountNumber", matcher);
|
||||
addAttributeIfNotAlreadyCaptured(artifact, ATTRIBUTE_TYPE.TSK_CARD_EXPIRATION, "expiration", matcher);
|
||||
addAttributeIfNotAlreadyCaptured(artifact, ATTRIBUTE_TYPE.TSK_CARD_SERVICE_CODE, "serviceCode", matcher);
|
||||
addAttributeIfNotAlreadyCaptured(artifact, ATTRIBUTE_TYPE.TSK_CARD_DISCRETIONARY, "discretionary", matcher);
|
||||
addAttributeIfNotAlreadyCaptured(artifact, ATTRIBUTE_TYPE.TSK_CARD_LRC, "LRC", matcher);
|
||||
|
||||
}
|
||||
|
||||
|