From f88388ac2e9e7e35283f4f9ec4b8e5a02de528ef Mon Sep 17 00:00:00 2001 From: Kelly Kelly Date: Thu, 21 May 2020 16:49:44 -0400 Subject: [PATCH] Added TagSet submenus and added TagSet name to TagName were applicable --- .../autopsy/actions/AddBookmarkTagAction.java | 5 +- .../autopsy/actions/AddTagAction.java | 114 +++++++------ ...DeleteFileBlackboardArtifactTagAction.java | 5 +- .../actions/DeleteFileContentTagAction.java | 5 +- .../actions/GetTagNameAndCommentDialog.java | 5 +- .../autopsy/actions/ReplaceTagAction.java | 151 +++++++++++------- .../casemodule/services/TagsManager.java | 52 ++---- .../org/sleuthkit/autopsy/datamodel/Tags.java | 7 +- .../SaveTaggedHashesToHashDbConfigPanel.java | 87 ++++------ .../sleuthkit/autopsy/tags/Bundle.properties | 14 ++ .../autopsy/tags/Bundle.properties-MERGED | 30 ++++ .../autopsy/tags/Bundle_ja.properties | 0 .../services => tags}/TagNameDefinition.java | 32 ++-- .../services => tags}/TagNameDialog.form | 0 .../services => tags}/TagNameDialog.java | 3 +- .../services => tags}/TagOptionsPanel.form | 4 +- .../services => tags}/TagOptionsPanel.java | 4 +- .../sleuthkit/autopsy/tags/TagUtilities.java | 69 ++++++++ .../TagsOptionsPanelController.java | 4 +- .../tag-options-panel-icon.png | Bin .../datamodel/DrawableTagsManager.java | 4 +- 21 files changed, 357 insertions(+), 238 deletions(-) create mode 100755 Core/src/org/sleuthkit/autopsy/tags/Bundle.properties create mode 100755 Core/src/org/sleuthkit/autopsy/tags/Bundle.properties-MERGED create mode 100755 Core/src/org/sleuthkit/autopsy/tags/Bundle_ja.properties rename Core/src/org/sleuthkit/autopsy/{casemodule/services => tags}/TagNameDefinition.java (93%) rename Core/src/org/sleuthkit/autopsy/{casemodule/services => tags}/TagNameDialog.form (100%) rename Core/src/org/sleuthkit/autopsy/{casemodule/services => tags}/TagNameDialog.java (99%) rename Core/src/org/sleuthkit/autopsy/{casemodule/services => tags}/TagOptionsPanel.form (99%) rename Core/src/org/sleuthkit/autopsy/{casemodule/services => tags}/TagOptionsPanel.java (99%) create mode 100755 Core/src/org/sleuthkit/autopsy/tags/TagUtilities.java rename Core/src/org/sleuthkit/autopsy/{casemodule/services => tags}/TagsOptionsPanelController.java (96%) rename Core/src/org/sleuthkit/autopsy/{casemodule/services => tags}/tag-options-panel-icon.png (100%) diff --git a/Core/src/org/sleuthkit/autopsy/actions/AddBookmarkTagAction.java b/Core/src/org/sleuthkit/autopsy/actions/AddBookmarkTagAction.java index d6090b2ace..ed9d7953a0 100644 --- a/Core/src/org/sleuthkit/autopsy/actions/AddBookmarkTagAction.java +++ b/Core/src/org/sleuthkit/autopsy/actions/AddBookmarkTagAction.java @@ -27,10 +27,10 @@ import java.util.Map; import java.util.logging.Level; import javax.swing.AbstractAction; import javax.swing.KeyStroke; -import org.openide.util.NbBundle; import org.openide.util.Utilities; import org.sleuthkit.autopsy.casemodule.Case; import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException; +import org.sleuthkit.autopsy.casemodule.services.TagsManager; import org.sleuthkit.autopsy.coreutils.Logger; import org.sleuthkit.datamodel.BlackboardArtifact; import org.sleuthkit.datamodel.TagName; @@ -40,13 +40,12 @@ public class AddBookmarkTagAction extends AbstractAction { public static final KeyStroke BOOKMARK_SHORTCUT = KeyStroke.getKeyStroke(KeyEvent.VK_B, InputEvent.CTRL_MASK); private static final String NO_COMMENT = ""; - private static final String BOOKMARK = NbBundle.getMessage(AddBookmarkTagAction.class, "AddBookmarkTagAction.bookmark.text"); @Override public void actionPerformed(ActionEvent e) { try { Map tagNamesMap = Case.getCurrentCaseThrows().getServices().getTagsManager().getDisplayNamesToTagNamesMap(); - TagName bookmarkTagName = tagNamesMap.get(BOOKMARK); + TagName bookmarkTagName = tagNamesMap.get(TagsManager.getBookmarkTagDisplayName()); /* * Both AddContentTagAction.addTag and diff --git a/Core/src/org/sleuthkit/autopsy/actions/AddTagAction.java b/Core/src/org/sleuthkit/autopsy/actions/AddTagAction.java index 3709592e62..53cf076c2e 100644 --- a/Core/src/org/sleuthkit/autopsy/actions/AddTagAction.java +++ b/Core/src/org/sleuthkit/autopsy/actions/AddTagAction.java @@ -22,6 +22,7 @@ import java.awt.event.ActionEvent; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; +import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Map; @@ -38,6 +39,7 @@ import org.sleuthkit.autopsy.casemodule.services.TagsManager; import org.sleuthkit.autopsy.coreutils.Logger; import org.sleuthkit.datamodel.Content; import org.sleuthkit.datamodel.TagName; +import org.sleuthkit.datamodel.TagSet; import org.sleuthkit.datamodel.TskCoreException; import org.sleuthkit.datamodel.TskData; @@ -126,37 +128,35 @@ abstract class AddTagAction extends AbstractAction implements Presenter.Popup { // Get the current set of tag names. Map tagNamesMap = null; List standardTagNames = TagsManager.getStandardTagNames(); + Map tagSetMenuMap = new HashMap<>(); + List standardTagMenuitems = new ArrayList<>(); try { TagsManager tagsManager = Case.getCurrentCaseThrows().getServices().getTagsManager(); tagNamesMap = new TreeMap<>(tagsManager.getDisplayNamesToTagNamesMap()); - } catch (TskCoreException | NoCurrentCaseException ex) { - Logger.getLogger(TagsManager.class.getName()).log(Level.SEVERE, "Failed to get tag names", ex); //NON-NLS - } - // Create a menu item for each of the existing and visible tags. - // Selecting one of these menu items adds a tag with the associated tag name. - List standardTagMenuitems = new ArrayList<>(); - if (null != tagNamesMap && !tagNamesMap.isEmpty()) { - for (Map.Entry entry : tagNamesMap.entrySet()) { - String tagDisplayName = entry.getKey(); - String notableString = entry.getValue().getKnownStatus() == TskData.FileKnown.BAD ? TagsManager.getNotableTagLabel() : ""; - JMenuItem tagNameItem = new JMenuItem(tagDisplayName + notableString); - // for the bookmark tag name only, added shortcut label - if (tagDisplayName.equals(NbBundle.getMessage(AddTagAction.class, "AddBookmarkTagAction.bookmark.text"))) { - tagNameItem.setAccelerator(AddBookmarkTagAction.BOOKMARK_SHORTCUT); - } + // Create a menu item for each of the existing and visible tags. + // Selecting one of these menu items adds a tag with the associated tag name. + if (!tagNamesMap.isEmpty()) { + for (Map.Entry entry : tagNamesMap.entrySet()) { + TagName tagName = entry.getValue(); + TagSet tagSet = tagName.getTagSet(); - tagNameItem.addActionListener((ActionEvent e) -> { - getAndAddTag(entry.getKey(), entry.getValue(), NO_COMMENT); - }); - - // Show custom tags before predefined tags in the menu - if (standardTagNames.contains(tagDisplayName)) { - standardTagMenuitems.add(tagNameItem); - } else { - add(tagNameItem); + // Show custom tags before predefined tags in the menu + if (tagSet != null) { + JMenu menu = tagSetMenuMap.get(tagSet.getName()); + if (menu == null) { + menu = createSubmenuForTagSet(tagSet); + tagSetMenuMap.put(tagSet.getName(), menu); + } + } else if (standardTagNames.contains(tagName.getDisplayName())) { + standardTagMenuitems.add(createMenutItem(tagName)); + } else { + add(createMenutItem(tagName)); + } } } + } catch (TskCoreException | NoCurrentCaseException ex) { + Logger.getLogger(TagsManager.class.getName()).log(Level.SEVERE, "Failed to get tag names", ex); //NON-NLS } if (getItemCount() > 0) { @@ -167,6 +167,10 @@ abstract class AddTagAction extends AbstractAction implements Presenter.Popup { add(menuItem); }); + tagSetMenuMap.values().forEach((menu) -> { + add(menu); + }); + addSeparator(); // Create a "Choose Tag and Comment..." menu item. Selecting this item initiates @@ -197,40 +201,44 @@ abstract class AddTagAction extends AbstractAction implements Presenter.Popup { } /** - * 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. + * Build a JMenu for the given TagSet. * - * @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 + * @param tagSet + * + * @return JMenu for the given TagSet */ - private void getAndAddTag(String tagDisplayName, TagName tagName, String comment) { - Case openCase; - try { - openCase = Case.getCurrentCaseThrows(); - } catch (NoCurrentCaseException ex) { - Logger.getLogger(AddTagAction.class.getName()).log(Level.SEVERE, "Exception while getting open case.", ex); // NON-NLS - return; + private JMenu createSubmenuForTagSet(TagSet tagSet) { + JMenu menu = new JMenu(tagSet.getName()); + List tagNameList = tagSet.getTagNames(); + + for (TagName tagName : tagNameList) { + menu.add(createMenutItem(tagName)); } - if (tagName == null) { - try { - tagName = openCase.getServices().getTagsManager().addTagName(tagDisplayName); - } catch (TagsManager.TagNameAlreadyExistsException ex) { - try { - tagName = openCase.getServices().getTagsManager().getDisplayNamesToTagNamesMap().get(tagDisplayName); - } catch (TskCoreException ex1) { - Logger.getLogger(AddTagAction.class.getName()).log(Level.SEVERE, tagDisplayName + " already exists in database but an error occurred in retrieving it.", ex1); //NON-NLS - } - } catch (TskCoreException ex) { - Logger.getLogger(AddTagAction.class.getName()).log(Level.SEVERE, "Error adding " + tagDisplayName + " tag name", ex); //NON-NLS - } + return menu; + } + + /** + * Create a menu item for the given TagName. + * + * @param tagName TagName from which to create the menu item. + * + * @return Menu item for given TagName. + */ + private JMenuItem createMenutItem(TagName tagName) { + String tagDisplayName = tagName.getDisplayName(); + String notableString = tagName.getKnownStatus() == TskData.FileKnown.BAD ? TagsManager.getNotableTagLabel() : ""; + JMenuItem tagNameItem = new JMenuItem(tagDisplayName + notableString); + + if (tagDisplayName.equals(TagsManager.getBookmarkTagDisplayName())) { + tagNameItem.setAccelerator(AddBookmarkTagAction.BOOKMARK_SHORTCUT); } - addTag(tagName, comment); + + tagNameItem.addActionListener((ActionEvent e) -> { + addTag(tagName, NO_COMMENT); + }); + + return tagNameItem; } } } diff --git a/Core/src/org/sleuthkit/autopsy/actions/DeleteFileBlackboardArtifactTagAction.java b/Core/src/org/sleuthkit/autopsy/actions/DeleteFileBlackboardArtifactTagAction.java index ec846567aa..fda1d02510 100644 --- a/Core/src/org/sleuthkit/autopsy/actions/DeleteFileBlackboardArtifactTagAction.java +++ b/Core/src/org/sleuthkit/autopsy/actions/DeleteFileBlackboardArtifactTagAction.java @@ -40,11 +40,11 @@ import org.sleuthkit.autopsy.casemodule.Case; import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException; import org.sleuthkit.autopsy.casemodule.services.TagsManager; import org.sleuthkit.autopsy.coreutils.Logger; +import org.sleuthkit.autopsy.tags.TagUtilities; import org.sleuthkit.datamodel.BlackboardArtifact; import org.sleuthkit.datamodel.BlackboardArtifactTag; import org.sleuthkit.datamodel.TagName; import org.sleuthkit.datamodel.TskCoreException; -import org.sleuthkit.datamodel.TskData; /** * Instances of this Action allow users to delete tags applied to blackboard @@ -194,8 +194,7 @@ public class DeleteFileBlackboardArtifactTagAction extends AbstractAction implem TagName tagName = entry.getValue(); for (BlackboardArtifactTag artifactTag : existingTagsList) { if (tagDisplayName.equals(artifactTag.getName().getDisplayName())) { - String notableString = tagName.getKnownStatus() == TskData.FileKnown.BAD ? TagsManager.getNotableTagLabel() : ""; - JMenuItem tagNameItem = new JMenuItem(tagDisplayName + notableString); + JMenuItem tagNameItem = new JMenuItem(TagUtilities.getDecoratedTagDisplayName(tagName)); tagNameItem.addActionListener((ActionEvent e) -> { deleteTag(tagName, artifactTag, artifact.getArtifactID()); }); diff --git a/Core/src/org/sleuthkit/autopsy/actions/DeleteFileContentTagAction.java b/Core/src/org/sleuthkit/autopsy/actions/DeleteFileContentTagAction.java index f68017de19..e0ca32817c 100644 --- a/Core/src/org/sleuthkit/autopsy/actions/DeleteFileContentTagAction.java +++ b/Core/src/org/sleuthkit/autopsy/actions/DeleteFileContentTagAction.java @@ -40,11 +40,11 @@ import org.sleuthkit.autopsy.casemodule.Case; import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException; import org.sleuthkit.autopsy.casemodule.services.TagsManager; import org.sleuthkit.autopsy.coreutils.Logger; +import org.sleuthkit.autopsy.tags.TagUtilities; import org.sleuthkit.datamodel.AbstractFile; import org.sleuthkit.datamodel.ContentTag; import org.sleuthkit.datamodel.TagName; import org.sleuthkit.datamodel.TskCoreException; -import org.sleuthkit.datamodel.TskData; /** * Instances of this Action allow users to delete tags applied to content. @@ -199,8 +199,7 @@ public class DeleteFileContentTagAction extends AbstractAction implements Presen TagName tagName = entry.getValue(); for (ContentTag contentTag : existingTagsList) { if (tagDisplayName.equals(contentTag.getName().getDisplayName())) { - String notableString = tagName.getKnownStatus() == TskData.FileKnown.BAD ? TagsManager.getNotableTagLabel() : ""; - JMenuItem tagNameItem = new JMenuItem(tagDisplayName + notableString); + JMenuItem tagNameItem = new JMenuItem(TagUtilities.getDecoratedTagDisplayName(tagName)); tagNameItem.addActionListener((ActionEvent e) -> { deleteTag(tagName, contentTag, file.getId()); }); diff --git a/Core/src/org/sleuthkit/autopsy/actions/GetTagNameAndCommentDialog.java b/Core/src/org/sleuthkit/autopsy/actions/GetTagNameAndCommentDialog.java index cf0c27fb27..3dccbc9cb8 100644 --- a/Core/src/org/sleuthkit/autopsy/actions/GetTagNameAndCommentDialog.java +++ b/Core/src/org/sleuthkit/autopsy/actions/GetTagNameAndCommentDialog.java @@ -41,9 +41,9 @@ import org.sleuthkit.autopsy.casemodule.Case; import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException; import org.sleuthkit.autopsy.casemodule.services.TagsManager; import org.sleuthkit.autopsy.coreutils.Logger; +import org.sleuthkit.autopsy.tags.TagUtilities; import org.sleuthkit.datamodel.TagName; import org.sleuthkit.datamodel.TskCoreException; -import org.sleuthkit.datamodel.TskData; /** * This dialog allows tag assignment with a comment attached. @@ -128,8 +128,7 @@ public class GetTagNameAndCommentDialog extends JDialog { @Override public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) { - String status = ((TagName) value).getKnownStatus() == TskData.FileKnown.BAD ? TagsManager.getNotableTagLabel() : ""; - String newValue = ((TagName) value).getDisplayName() + status; + String newValue = TagUtilities.getDecoratedTagDisplayName((TagName) value); return super.getListCellRendererComponent(list, newValue, index, isSelected, cellHasFocus); } }); diff --git a/Core/src/org/sleuthkit/autopsy/actions/ReplaceTagAction.java b/Core/src/org/sleuthkit/autopsy/actions/ReplaceTagAction.java index 79ca4f4739..09d5d5ba6b 100644 --- a/Core/src/org/sleuthkit/autopsy/actions/ReplaceTagAction.java +++ b/Core/src/org/sleuthkit/autopsy/actions/ReplaceTagAction.java @@ -21,6 +21,7 @@ package org.sleuthkit.autopsy.actions; import java.awt.event.ActionEvent; import java.util.ArrayList; import java.util.Collection; +import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Map; @@ -38,6 +39,7 @@ import org.sleuthkit.autopsy.casemodule.services.TagsManager; import org.sleuthkit.autopsy.coreutils.Logger; import org.sleuthkit.datamodel.Tag; import org.sleuthkit.datamodel.TagName; +import org.sleuthkit.datamodel.TagSet; import org.sleuthkit.datamodel.TskCoreException; import org.sleuthkit.datamodel.TskData; @@ -60,10 +62,10 @@ abstract class ReplaceTagAction extends AbstractAction implements } /** - * Subclasses of replaceTagAction should not override actionPerformed, - * but instead override replaceTag. - * - * @param event + * Subclasses of replaceTagAction should not override actionPerformed, but + * instead override replaceTag. + * + * @param event */ @Override @SuppressWarnings("NoopMethodInAbstractClass") @@ -77,9 +79,10 @@ abstract class ReplaceTagAction extends AbstractAction implements /** * Method to actually replace the selected tag with the given new tag * - * @param oldTag - the TagName which is being removed from the item + * @param oldTag - the TagName which is being removed from the item * @param newTagName - the TagName which is being added to the itme - * @param comment the comment associated with the tag, empty string for no comment + * @param comment the comment associated with the tag, empty string for + * no comment */ abstract protected void replaceTag(T oldTag, TagName newTagName, String comment); @@ -90,7 +93,6 @@ abstract class ReplaceTagAction extends AbstractAction implements */ abstract Collection getTagsToReplace(); - @Override public JMenuItem getPopupPresenter() { return new ReplaceTagMenu(); @@ -108,60 +110,50 @@ abstract class ReplaceTagAction extends AbstractAction implements super(getActionDisplayName()); final Collection selectedTags = getTagsToReplace(); - + // Get the current set of tag names. Map tagNamesMap = null; List standardTagNames = TagsManager.getStandardTagNames(); - try { - TagsManager tagsManager = Case.getCurrentCaseThrows().getServices().getTagsManager(); - tagNamesMap = new TreeMap<>(tagsManager.getDisplayNamesToTagNamesMap()); - } catch (TskCoreException | NoCurrentCaseException ex) { - Logger.getLogger(ReplaceTagMenu.class.getName()).log(Level.SEVERE, "Failed to get tag names", ex); //NON-NLS - } - + Map tagSetMenuMap = new HashMap<>(); List standardTagMenuitems = new ArrayList<>(); // Ideally we should'nt allow user to pick a replacement tag that's already been applied to an item // In the very least we don't allow them to pick the same tag as the one they are trying to replace Set existingTagNames = new HashSet<>(); - if (!selectedTags.isEmpty()) { - T firstTag = selectedTags.iterator().next(); - existingTagNames.add(firstTag.getName().getDisplayName()); - } - - if (null != tagNamesMap && !tagNamesMap.isEmpty()) { - for (Map.Entry entry : tagNamesMap.entrySet()) { - String tagDisplayName = entry.getKey(); - String notableString = entry.getValue().getKnownStatus() == TskData.FileKnown.BAD ? TagsManager.getNotableTagLabel() : ""; - JMenuItem tagNameItem = new JMenuItem(tagDisplayName + notableString); - // for the bookmark tag name only, added shortcut label - if (tagDisplayName.equals(NbBundle.getMessage(AddTagAction.class, "AddBookmarkTagAction.bookmark.text"))) { - tagNameItem.setAccelerator(AddBookmarkTagAction.BOOKMARK_SHORTCUT); - } + try { + TagsManager tagsManager = Case.getCurrentCaseThrows().getServices().getTagsManager(); + tagNamesMap = new TreeMap<>(tagsManager.getDisplayNamesToTagNamesMap()); - // Add action to replace the tag - tagNameItem.addActionListener((ActionEvent event) -> { - selectedTags.forEach((oldtag) -> { - replaceTag(oldtag, entry.getValue(), oldtag.getComment()); - }); - }); - - // Don't allow replacing a tag with same tag. - if (existingTagNames.contains(tagDisplayName)) { - tagNameItem.setEnabled(false); - } - - - // Show custom tags before predefined tags in the menu - if (standardTagNames.contains(tagDisplayName)) { - standardTagMenuitems.add(tagNameItem); - } else { - add(tagNameItem); - } + if (!selectedTags.isEmpty()) { + T firstTag = selectedTags.iterator().next(); + existingTagNames.add(firstTag.getName().getDisplayName()); } - } else { - JMenuItem empty = new JMenuItem(NbBundle.getMessage(this.getClass(), "AddTagAction.noTags")); - empty.setEnabled(false); - add(empty); + + if (!tagNamesMap.isEmpty()) { + for (Map.Entry entry : tagNamesMap.entrySet()) { + TagName tagName = entry.getValue(); + TagSet tagSet = tagName.getTagSet(); + + // Show custom tags before predefined tags in the menu + if (tagSet != null) { + JMenu menu = tagSetMenuMap.get(tagSet.getName()); + if (menu == null) { + menu = createSubmenuForTagSet(tagSet, existingTagNames, selectedTags); + tagSetMenuMap.put(tagSet.getName(), menu); + } + } else if (standardTagNames.contains(tagName.getDisplayName())) { + standardTagMenuitems.add(createMenutItem(tagName, existingTagNames, selectedTags)); + } else { + add(createMenutItem(tagName, existingTagNames, selectedTags)); + } + } + } else { + JMenuItem empty = new JMenuItem(NbBundle.getMessage(this.getClass(), "AddTagAction.noTags")); + empty.setEnabled(false); + add(empty); + } + + } catch (TskCoreException | NoCurrentCaseException ex) { + Logger.getLogger(ReplaceTagMenu.class.getName()).log(Level.SEVERE, "Failed to get tag names", ex); //NON-NLS } // @@ -171,7 +163,11 @@ abstract class ReplaceTagAction extends AbstractAction implements standardTagMenuitems.forEach((menuItem) -> { add(menuItem); }); - + + tagSetMenuMap.values().forEach((menuItem) -> { + add(menuItem); + }); + addSeparator(); JMenuItem newTagMenuItem = new JMenuItem(NbBundle.getMessage(this.getClass(), "AddTagAction.newTag")); newTagMenuItem.addActionListener((ActionEvent event) -> { @@ -183,7 +179,7 @@ abstract class ReplaceTagAction extends AbstractAction implements } }); add(newTagMenuItem); - // Create a "Choose Tag and Comment..." menu item. Selecting this item initiates + // Create a "Choose Tag and Comment..." menu item. Selecting this item initiates // a dialog that can be used to create or select a tag name with an // optional comment and adds a tag with the resulting name. JMenuItem tagAndCommentItem = new JMenuItem(NbBundle.getMessage(this.getClass(), "AddTagAction.tagAndComment")); @@ -195,7 +191,52 @@ abstract class ReplaceTagAction extends AbstractAction implements }); } }); - add(tagAndCommentItem); + add(tagAndCommentItem); } } + + /** + * Build a JMenu for the given TagSet. + * + * @param tagSet + * + * @return JMenu for the given TagSet + */ + private JMenu createSubmenuForTagSet(TagSet tagSet, Set tagNamesToDisable, Collection selectedTags) { + JMenu menu = new JMenu(tagSet.getName()); + List tagNameList = tagSet.getTagNames(); + + for (TagName tagName : tagNameList) { + menu.add(createMenutItem(tagName, tagNamesToDisable, selectedTags)); + } + + return menu; + } + + /** + * Create a menu item for the given TagName. + * + * @param tagName TagName from which to create the menu item. + * + * @return Menu item for given TagName. + */ + private JMenuItem createMenutItem(TagName tagName, Set tagNamesToDisable, Collection selectedTags) { + String tagDisplayName = tagName.getDisplayName(); + String notableString = tagName.getKnownStatus() == TskData.FileKnown.BAD ? TagsManager.getNotableTagLabel() : ""; + JMenuItem tagNameItem = new JMenuItem(tagDisplayName + notableString); + + if (tagDisplayName.equals(TagsManager.getBookmarkTagDisplayName())) { + tagNameItem.setAccelerator(AddBookmarkTagAction.BOOKMARK_SHORTCUT); + } + + tagNameItem.addActionListener((ActionEvent e) -> { + selectedTags.forEach((oldtag) -> { + replaceTag(oldtag, tagName, oldtag.getComment()); + }); + }); + + tagNameItem.setEnabled(!tagNamesToDisable.contains(tagDisplayName)); + + return tagNameItem; + } } diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/services/TagsManager.java b/Core/src/org/sleuthkit/autopsy/casemodule/services/TagsManager.java index 565d761b47..dfe9e2da17 100755 --- a/Core/src/org/sleuthkit/autopsy/casemodule/services/TagsManager.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/services/TagsManager.java @@ -18,6 +18,7 @@ */ package org.sleuthkit.autopsy.casemodule.services; +import org.sleuthkit.autopsy.tags.TagNameDefinition; import java.io.Closeable; import java.io.IOException; import java.util.ArrayList; @@ -147,10 +148,11 @@ public class TagsManager implements Closeable { } /** - * Gets the set of display names of notable (TskData.FileKnown.BAD) tag types. - * If a case is not open the list will only include only the user defined - * custom tags. Otherwise the list will include all notable tags. - * @return + * Gets the set of display names of notable (TskData.FileKnown.BAD) tag + * types. If a case is not open the list will only include only the user + * defined custom tags. Otherwise the list will include all notable tags. + * + * @return */ public static List getNotableTagDisplayNames() { List tagDisplayNames = new ArrayList<>(); @@ -159,12 +161,12 @@ public class TagsManager implements Closeable { tagDisplayNames.add(tagDef.getDisplayName()); } } - - try { + + try { TagsManager tagsManager = Case.getCurrentCaseThrows().getServices().getTagsManager(); for (TagName tagName : tagsManager.getAllTagNames()) { - if(tagName.getKnownStatus() == TskData.FileKnown.BAD && - !tagDisplayNames.contains(tagName.getDisplayName())) { + if (tagName.getKnownStatus() == TskData.FileKnown.BAD + && !tagDisplayNames.contains(tagName.getDisplayName())) { tagDisplayNames.add(tagName.getDisplayName()); } } @@ -172,7 +174,7 @@ public class TagsManager implements Closeable { /* * No current case, nothing more to add to the set. */ - } catch(TskCoreException ex) { + } catch (TskCoreException ex) { LOGGER.log(Level.SEVERE, "Failed to get list of TagNames from TagsManager.", ex); } return tagDisplayNames; @@ -220,7 +222,7 @@ public class TagsManager implements Closeable { * * @return */ - public static String getBookmarkDisplayString() { + public static String getBookmarkTagDisplayName() { return TagNameDefinition.getBookmarkDisplayString(); } @@ -229,7 +231,7 @@ public class TagsManager implements Closeable { * * @return */ - public static String getFollowUpDisplayString() { + public static String getFollowUpTagDisplayName() { return TagNameDefinition.getFollowUpDisplayString(); } @@ -238,7 +240,7 @@ public class TagsManager implements Closeable { * * @return */ - public static String getNotableDisplayString() { + public static String getNotableTagDisplayName() { return TagNameDefinition.getNotableDisplayString(); } @@ -376,39 +378,17 @@ public class TagsManager implements Closeable { /** * 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. * - * @return A map of tag display names to possibly null TagName object - * references. + * @return A map of tag display names to TagName object references. * * @throws TskCoreException if there is an error querying the case database. */ public Map getDisplayNamesToTagNamesMap() throws TskCoreException { - /** - * Order is important here. The keys (display names) for the 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. Standard tag - * names are added during the initialization of the case database. - * - * 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 tagNames = new HashMap<>(); - Set customTypes = TagNameDefinition.getTagNameDefinitions(); - for (TagNameDefinition tagType : customTypes) { - tagNames.put(tagType.getDisplayName(), null); - } for (TagName tagName : caseDb.getAllTagNames()) { tagNames.put(tagName.getDisplayName(), tagName); } - return new HashMap<>(tagNames); + return tagNames; } /** diff --git a/Core/src/org/sleuthkit/autopsy/datamodel/Tags.java b/Core/src/org/sleuthkit/autopsy/datamodel/Tags.java index aa47872c82..827cbc4f03 100644 --- a/Core/src/org/sleuthkit/autopsy/datamodel/Tags.java +++ b/Core/src/org/sleuthkit/autopsy/datamodel/Tags.java @@ -39,6 +39,7 @@ import org.sleuthkit.autopsy.casemodule.services.TagsManager; import org.sleuthkit.autopsy.core.UserPreferences; import org.sleuthkit.autopsy.coreutils.Logger; import org.sleuthkit.autopsy.ingest.IngestManager; +import org.sleuthkit.autopsy.tags.TagUtilities; import org.sleuthkit.datamodel.BlackboardArtifactTag; import org.sleuthkit.datamodel.ContentTag; import org.sleuthkit.datamodel.TagName; @@ -284,9 +285,9 @@ public class Tags implements AutopsyVisitableItem { public TagNameNode(TagName tagName) { super(Children.create(new TagTypeNodeFactory(tagName), true), Lookups.singleton(NbBundle.getMessage(TagNameNode.class, "TagNameNode.namePlusTags.text", tagName.getDisplayName()))); this.tagName = tagName; - setName(tagName.getDisplayName()); + setName(TagUtilities.getDecoratedTagDisplayName(tagName)); updateDisplayName(); - if (tagName.getDisplayName().equals(NbBundle.getMessage(this.getClass(), "TagNameNode.bookmark.text"))) { + if (tagName.getDisplayName().equals(TagsManager.getBookmarkTagDisplayName())) { setIconBaseWithExtension(BOOKMARK_TAG_ICON_PATH); } else { setIconBaseWithExtension(ICON_PATH); @@ -319,7 +320,7 @@ public class Tags implements AutopsyVisitableItem { } catch (TskCoreException | NoCurrentCaseException ex) { Logger.getLogger(TagNameNode.class.getName()).log(Level.SEVERE, "Failed to get tags count for " + tagName.getDisplayName() + " tag name", ex); //NON-NLS } - setDisplayName(tagName.getDisplayName() + " \u200E(\u200E" + tagsCount + ")\u200E"); + setDisplayName(TagUtilities.getDecoratedTagDisplayName(tagName) + " \u200E(\u200E" + tagsCount + ")\u200E"); } @Override diff --git a/Core/src/org/sleuthkit/autopsy/report/modules/taggedhashes/SaveTaggedHashesToHashDbConfigPanel.java b/Core/src/org/sleuthkit/autopsy/report/modules/taggedhashes/SaveTaggedHashesToHashDbConfigPanel.java index dfd66b64c0..c9ece2ccf5 100644 --- a/Core/src/org/sleuthkit/autopsy/report/modules/taggedhashes/SaveTaggedHashesToHashDbConfigPanel.java +++ b/Core/src/org/sleuthkit/autopsy/report/modules/taggedhashes/SaveTaggedHashesToHashDbConfigPanel.java @@ -29,19 +29,19 @@ import java.util.List; import java.util.Map; import java.util.Objects; import java.util.logging.Level; +import javax.swing.DefaultListModel; import javax.swing.JCheckBox; import javax.swing.JLabel; import javax.swing.JList; import javax.swing.JOptionPane; import javax.swing.ListCellRenderer; -import javax.swing.ListModel; -import javax.swing.event.ListDataListener; import org.sleuthkit.autopsy.casemodule.Case; import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException; import org.sleuthkit.autopsy.coreutils.Logger; import org.sleuthkit.autopsy.modules.hashdatabase.HashDbManager.HashDb; import org.sleuthkit.autopsy.modules.hashdatabase.HashDbManager; import org.sleuthkit.autopsy.modules.hashdatabase.HashLookupSettingsPanel; +import org.sleuthkit.autopsy.tags.TagUtilities; import org.sleuthkit.datamodel.TagName; import org.sleuthkit.datamodel.TskCoreException; @@ -54,9 +54,9 @@ class SaveTaggedHashesToHashDbConfigPanel extends javax.swing.JPanel { private static final long serialVersionUID = 1L; private List tagNames; - private Map tagNameSelections = new LinkedHashMap<>(); - private TagNamesListModel tagsNamesListModel; - private TagsNamesListCellRenderer tagsNamesRenderer; + private Map tagNameSelections = new LinkedHashMap<>(); + private DefaultListModel tagsNamesListModel = new DefaultListModel<>(); + private TagsNamesListCellRenderer tagsNamesRenderer = new TagsNamesListCellRenderer(); private String selectedHashSetName; private List updateableHashSets = new ArrayList<>(); @@ -67,9 +67,6 @@ class SaveTaggedHashesToHashDbConfigPanel extends javax.swing.JPanel { // Set up the tag names JList component to be a collection of check boxes // for selecting tag names. The mouse click listener updates tagNameSelections // to reflect user choices. - //tagNamesListBox.setModel(tagsNamesListModel); - //tagNamesListBox.setCellRenderer(tagsNamesRenderer); - //tagNamesListBox.setVisibleRowCount(-1); tagNamesListBox.addMouseListener(new MouseAdapter() { @Override public void mousePressed(MouseEvent evt) { @@ -79,13 +76,13 @@ class SaveTaggedHashesToHashDbConfigPanel extends javax.swing.JPanel { JList list = (JList) evt.getSource(); int index = list.locationToIndex(evt.getPoint()); if (index > -1) { - String value = tagsNamesListModel.getElementAt(index); - tagNameSelections.put(value, !tagNameSelections.get(value)); + TagName tagName = tagsNamesListModel.getElementAt(index); + tagNameSelections.put(tagName, !tagNameSelections.get(tagName)); list.repaint(); } } }); - + this.jAllTagsCheckBox.addItemListener(new ItemListener() { @Override public void itemStateChanged(ItemEvent e) { @@ -96,22 +93,22 @@ class SaveTaggedHashesToHashDbConfigPanel extends javax.swing.JPanel { } }); } - + HashesReportModuleSettings getConfiguration() { return new HashesReportModuleSettings(jAllTagsCheckBox.isSelected(), selectedHashSetName); } - + void setConfiguration(HashesReportModuleSettings settings) { // Need to reset tags. User may have opened a different case or // there may not be a case open any more (Command Line wizard). customizeComponents(); - + // update tag selection jAllTagsCheckBox.setSelected(settings.isExportAllTags()); if (settings.isExportAllTags()) { selectAllTags(true); } - + // update hash database selection if (settings.getHashDbName() != null) { populateHashSetComponents(); @@ -119,25 +116,28 @@ class SaveTaggedHashesToHashDbConfigPanel extends javax.swing.JPanel { } } - private void customizeComponents() { - populateTagNameComponents(); - - tagsNamesListModel = new TagNamesListModel(); + private void customizeComponents() { + tagsNamesListModel = new DefaultListModel<>(); tagsNamesRenderer = new TagsNamesListCellRenderer(); + populateTagNameComponents(); + tagNamesListBox.setModel(tagsNamesListModel); tagNamesListBox.setCellRenderer(tagsNamesRenderer); tagNamesListBox.setVisibleRowCount(-1); - + populateHashSetComponents(); } private void populateTagNameComponents() { // Get the tag names in use for the current case. tagNames = new ArrayList<>(); - Map updatedTagNameSelections = new LinkedHashMap<>(); + Map updatedTagNameSelections = new LinkedHashMap<>(); try { // There may not be a case open when configuring report modules for Command Line execution tagNames = Case.getCurrentCaseThrows().getServices().getTagsManager().getTagNamesInUse(); + for (TagName tagName : tagNames) { + tagsNamesListModel.addElement(tagName); + } } catch (TskCoreException ex) { Logger.getLogger(SaveTaggedHashesToHashDbConfigPanel.class.getName()).log(Level.SEVERE, "Failed to get tag names", ex); } catch (NoCurrentCaseException ex) { @@ -151,10 +151,10 @@ class SaveTaggedHashesToHashDbConfigPanel extends javax.swing.JPanel { // LinkedHashMap so that order is preserved and the tagNames and tagNameSelections // containers are "parallel" containers. for (TagName tagName : tagNames) { - if (tagNameSelections.get(tagName.getDisplayName()) != null && Objects.equals(tagNameSelections.get(tagName.getDisplayName()), Boolean.TRUE)) { - updatedTagNameSelections.put(tagName.getDisplayName(), Boolean.TRUE); + if (tagNameSelections.get(tagName) != null && Objects.equals(tagNameSelections.get(tagName), Boolean.TRUE)) { + updatedTagNameSelections.put(tagName, Boolean.TRUE); } else { - updatedTagNameSelections.put(tagName.getDisplayName(), Boolean.FALSE); + updatedTagNameSelections.put(tagName, Boolean.FALSE); } } tagNameSelections = updatedTagNameSelections; @@ -165,7 +165,7 @@ class SaveTaggedHashesToHashDbConfigPanel extends javax.swing.JPanel { // and when the user changes the hash set configuration. hashSetsComboBox.removeAllItems(); selectedHashSetName = ""; - + // Get the updateable hash databases and add their hash set names to the // JComboBox component. updateableHashSets = HashDbManager.getInstance().getUpdateableHashSets(); @@ -187,7 +187,7 @@ class SaveTaggedHashesToHashDbConfigPanel extends javax.swing.JPanel { List getSelectedTagNames() { List selectedTagNames = new ArrayList<>(); for (TagName tagName : tagNames) { - if (tagNameSelections.get(tagName.getDisplayName())) { + if (tagNameSelections.get(tagName)) { selectedTagNames.add(tagName); } } @@ -208,41 +208,20 @@ class SaveTaggedHashesToHashDbConfigPanel extends javax.swing.JPanel { return null; } - // This class is a list model for the tag names JList component. - private class TagNamesListModel implements ListModel { - - @Override - public int getSize() { - return tagNames.size(); - } - - @Override - public String getElementAt(int index) { - return tagNames.get(index).getDisplayName(); - } - - @Override - public void addListDataListener(ListDataListener l) { - } - - @Override - public void removeListDataListener(ListDataListener l) { - } - } - // This class renders the items in the tag names JList component as JCheckbox components. - private class TagsNamesListCellRenderer extends JCheckBox implements ListCellRenderer { + private class TagsNamesListCellRenderer extends JCheckBox implements ListCellRenderer { + private static final long serialVersionUID = 1L; @Override - public Component getListCellRendererComponent(JList list, String value, int index, boolean isSelected, boolean cellHasFocus) { + public Component getListCellRendererComponent(JList list, TagName value, int index, boolean isSelected, boolean cellHasFocus) { if (value != null) { setEnabled(list.isEnabled()); setSelected(tagNameSelections.get(value)); setFont(list.getFont()); setBackground(list.getBackground()); setForeground(list.getForeground()); - setText(value); + setText(TagUtilities.getDecoratedTagDisplayName(value)); return this; } return new JLabel(); @@ -364,7 +343,7 @@ class SaveTaggedHashesToHashDbConfigPanel extends javax.swing.JPanel { }//GEN-LAST:event_selectAllButtonActionPerformed private void hashSetsComboBoxActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_hashSetsComboBoxActionPerformed - selectedHashSetName = (String)hashSetsComboBox.getSelectedItem(); + selectedHashSetName = (String) hashSetsComboBox.getSelectedItem(); }//GEN-LAST:event_hashSetsComboBoxActionPerformed private void deselectAllButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_deselectAllButtonActionPerformed @@ -389,7 +368,7 @@ class SaveTaggedHashesToHashDbConfigPanel extends javax.swing.JPanel { state = Boolean.FALSE; } for (TagName tagName : tagNames) { - tagNameSelections.put(tagName.getDisplayName(), state); + tagNameSelections.put(tagName, state); } tagNamesListBox.repaint(); } @@ -406,6 +385,6 @@ class SaveTaggedHashesToHashDbConfigPanel extends javax.swing.JPanel { private javax.swing.JLabel jLabel2; private javax.swing.JScrollPane jScrollPane1; private javax.swing.JButton selectAllButton; - private javax.swing.JList tagNamesListBox; + private javax.swing.JList tagNamesListBox; // End of variables declaration//GEN-END:variables } diff --git a/Core/src/org/sleuthkit/autopsy/tags/Bundle.properties b/Core/src/org/sleuthkit/autopsy/tags/Bundle.properties new file mode 100755 index 0000000000..e0da2c4cfd --- /dev/null +++ b/Core/src/org/sleuthkit/autopsy/tags/Bundle.properties @@ -0,0 +1,14 @@ +OptionsCategory_Name_TagNamesOptions=Tags +OptionsCategory_TagNames=TagNames +TagNameDialog.title.text=New Tag +TagNameDialog.JOptionPane.tagNameIllegalCharacters.message=Tag name may not contain any of the following symbols: \\ : * ? " < > | , ; +TagNameDialog.JOptionPane.tagNameIllegalCharacters.title=Invalid character in tag name +TagNameDialog.JOptionPane.tagNameEmpty.message=The tag name cannot be empty +TagNameDialog.JOptionPane.tagNameEmpty.title=Empty tag name +TagOptionsPanel.tagTypesListLabel.text=Tag Names: +TagOptionsPanel.deleteTagNameButton.text=Delete Tag +TagOptionsPanel.newTagNameButton.text=New Tag +TagNameDialog.okButton.text=OK +TagNameDialog.cancelButton.text=Cancel +TagNameDialog.tagNameTextField.text= +TagNameDialog.newTagNameLabel.text=Name: \ No newline at end of file diff --git a/Core/src/org/sleuthkit/autopsy/tags/Bundle.properties-MERGED b/Core/src/org/sleuthkit/autopsy/tags/Bundle.properties-MERGED new file mode 100755 index 0000000000..58d7bac856 --- /dev/null +++ b/Core/src/org/sleuthkit/autopsy/tags/Bundle.properties-MERGED @@ -0,0 +1,30 @@ +OptionsCategory_Name_TagNamesOptions=Tags +OptionsCategory_TagNames=TagNames +TagNameDefinition.predefTagNames.bookmark.text=Bookmark +TagNameDefinition.predefTagNames.followUp.text=Follow Up +TagNameDefinition.predefTagNames.notableItem.text=Notable Item +TagNameDialog.descriptionLabel.text=Description: +TagNameDialog.editTitle.text=Edit Tag +TagNameDialog.JOptionPane.tagDescriptionIllegalCharacters.message=Tag descriptions may not contain commas (,) or semicolons (;) +TagNameDialog.JOptionPane.tagDescriptionIllegalCharacters.title=Invalid character in tag description +TagNameDialog.notableCheckbox.text=Tag indicates item is notable. +TagNameDialog.title.text=New Tag +TagNameDialog.JOptionPane.tagNameIllegalCharacters.message=Tag name may not contain any of the following symbols: \\ : * ? " < > | , ; +TagNameDialog.JOptionPane.tagNameIllegalCharacters.title=Invalid character in tag name +TagNameDialog.JOptionPane.tagNameEmpty.message=The tag name cannot be empty +TagNameDialog.JOptionPane.tagNameEmpty.title=Empty tag name +TagOptionsPanel.descriptionLabel.text=Tag Description: +TagOptionsPanel.editTagNameButton.text=Edit Tag +TagOptionsPanel.ingestRunningWarningLabel.text=Cannot make changes to existing tags when ingest is running! +TagOptionsPanel.isNotableLabel.text=Tag indicates item is notable: +TagOptionsPanel.notableYesOrNoLabel.text= +TagOptionsPanel.panelDescriptionTextArea.text=Create and manage tags. Tags can be applied to files and results in the case. Notable tags will cause items tagged with them to be flagged as notable when using a central repository. Changing the status of a tag will only effect items in the current case. +TagOptionsPanel.TagNameDialog.tagNameAlreadyExists.message=Tag name must be unique. A tag with this name already exists. +TagOptionsPanel.TagNameDialog.tagNameAlreadyExists.title=Duplicate Tag Name +TagOptionsPanel.tagTypesListLabel.text=Tag Names: +TagOptionsPanel.deleteTagNameButton.text=Delete Tag +TagOptionsPanel.newTagNameButton.text=New Tag +TagNameDialog.okButton.text=OK +TagNameDialog.cancelButton.text=Cancel +TagNameDialog.tagNameTextField.text= +TagNameDialog.newTagNameLabel.text=Name: diff --git a/Core/src/org/sleuthkit/autopsy/tags/Bundle_ja.properties b/Core/src/org/sleuthkit/autopsy/tags/Bundle_ja.properties new file mode 100755 index 0000000000..e69de29bb2 diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/services/TagNameDefinition.java b/Core/src/org/sleuthkit/autopsy/tags/TagNameDefinition.java similarity index 93% rename from Core/src/org/sleuthkit/autopsy/casemodule/services/TagNameDefinition.java rename to Core/src/org/sleuthkit/autopsy/tags/TagNameDefinition.java index 7cccbca405..613e368d2f 100755 --- a/Core/src/org/sleuthkit/autopsy/casemodule/services/TagNameDefinition.java +++ b/Core/src/org/sleuthkit/autopsy/tags/TagNameDefinition.java @@ -16,7 +16,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.sleuthkit.autopsy.casemodule.services; +package org.sleuthkit.autopsy.tags; import java.util.ArrayList; import java.util.Arrays; @@ -42,7 +42,7 @@ import org.sleuthkit.datamodel.TskData; * A tag name definition consisting of a display name, description and color. */ @Immutable -final class TagNameDefinition implements Comparable { +final public class TagNameDefinition implements Comparable { private static final Logger LOGGER = Logger.getLogger(TagNameDefinition.class.getName()); @Messages({ @@ -99,22 +99,22 @@ final class TagNameDefinition implements Comparable { * @param color The color for the tag name. * @param status The status denoted by the tag name. */ - TagNameDefinition(String displayName, String description, TagName.HTML_COLOR color, TskData.FileKnown status) { + public TagNameDefinition(String displayName, String description, TagName.HTML_COLOR color, TskData.FileKnown status) { this.displayName = displayName; this.description = description; this.color = color; this.knownStatus = status; } - static Collection getProjectVICDefaultDefinitions() { + static public Collection getProjectVICDefaultDefinitions() { return Collections.unmodifiableCollection(PROJECT_VIC_TAG_DEFINITIONS); } - static Collection getStandardTagNameDefinitions() { + static public Collection getStandardTagNameDefinitions() { return Collections.unmodifiableCollection(STANDARD_TAGS_DEFINITIONS); } - static List getStandardTagNames() { + static public List getStandardTagNames() { List strList = new ArrayList<>(); for (TagNameDefinition def : STANDARD_TAGS_DEFINITIONS) { @@ -133,7 +133,7 @@ final class TagNameDefinition implements Comparable { * * @return */ - static String getBookmarkDisplayString() { + static public String getBookmarkDisplayString() { return Bundle.TagNameDefinition_predefTagNames_bookmark_text(); } @@ -142,7 +142,7 @@ final class TagNameDefinition implements Comparable { * * @return */ - static String getFollowUpDisplayString() { + static public String getFollowUpDisplayString() { return Bundle.TagNameDefinition_predefTagNames_followUp_text(); } @@ -151,7 +151,7 @@ final class TagNameDefinition implements Comparable { * * @return */ - static String getNotableDisplayString() { + static public String getNotableDisplayString() { return Bundle.TagNameDefinition_predefTagNames_notableItem_text(); } @@ -160,7 +160,7 @@ final class TagNameDefinition implements Comparable { * * @return The display name. */ - String getDisplayName() { + public String getDisplayName() { return displayName; } @@ -169,7 +169,7 @@ final class TagNameDefinition implements Comparable { * * @return The description. */ - String getDescription() { + public String getDescription() { return description; } @@ -178,7 +178,7 @@ final class TagNameDefinition implements Comparable { * * @return The color. */ - TagName.HTML_COLOR getColor() { + public TagName.HTML_COLOR getColor() { return color; } @@ -187,7 +187,7 @@ final class TagNameDefinition implements Comparable { * * @return a value of TskData.FileKnown which is associated with this tag */ - TskData.FileKnown getKnownStatus() { + public TskData.FileKnown getKnownStatus() { return knownStatus; } @@ -255,7 +255,7 @@ final class TagNameDefinition implements Comparable { return displayName + "," + description + "," + color.name() + "," + knownStatus.toString(); } - TagName saveToCase(SleuthkitCase caseDb) { + public TagName saveToCase(SleuthkitCase caseDb) { TagName tagName = null; try { tagName = caseDb.addOrUpdateTagName(displayName, description, color, knownStatus); @@ -279,7 +279,7 @@ final class TagNameDefinition implements Comparable { * * @return A set of tag name definition objects. */ - static synchronized Set getTagNameDefinitions() { + public static synchronized Set getTagNameDefinitions() { if (needsVersionUpdate()) { updateTagDefinitions(); } @@ -311,7 +311,7 @@ final class TagNameDefinition implements Comparable { * * @param tagNames A set of tag name definition objects. */ - static synchronized void setTagNameDefinitions(Set tagNames) { + public static synchronized void setTagNameDefinitions(Set tagNames) { StringBuilder setting = new StringBuilder(); for (TagNameDefinition tagName : tagNames) { if (setting.length() != 0) { diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/services/TagNameDialog.form b/Core/src/org/sleuthkit/autopsy/tags/TagNameDialog.form similarity index 100% rename from Core/src/org/sleuthkit/autopsy/casemodule/services/TagNameDialog.form rename to Core/src/org/sleuthkit/autopsy/tags/TagNameDialog.form diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/services/TagNameDialog.java b/Core/src/org/sleuthkit/autopsy/tags/TagNameDialog.java similarity index 99% rename from Core/src/org/sleuthkit/autopsy/casemodule/services/TagNameDialog.java rename to Core/src/org/sleuthkit/autopsy/tags/TagNameDialog.java index 79207aaaaa..e771c3653d 100755 --- a/Core/src/org/sleuthkit/autopsy/casemodule/services/TagNameDialog.java +++ b/Core/src/org/sleuthkit/autopsy/tags/TagNameDialog.java @@ -16,7 +16,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.sleuthkit.autopsy.casemodule.services; +package org.sleuthkit.autopsy.tags; import java.awt.BorderLayout; import java.awt.event.WindowAdapter; @@ -28,6 +28,7 @@ import javax.swing.event.DocumentListener; import org.openide.util.NbBundle; import org.openide.util.NbBundle.Messages; import org.openide.windows.WindowManager; +import org.sleuthkit.autopsy.casemodule.services.TagsManager; import org.sleuthkit.datamodel.TskData; @Messages({"TagNameDialog.descriptionLabel.text=Description:", diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/services/TagOptionsPanel.form b/Core/src/org/sleuthkit/autopsy/tags/TagOptionsPanel.form similarity index 99% rename from Core/src/org/sleuthkit/autopsy/casemodule/services/TagOptionsPanel.form rename to Core/src/org/sleuthkit/autopsy/tags/TagOptionsPanel.form index 0af895f91a..5ad6c2b256 100644 --- a/Core/src/org/sleuthkit/autopsy/casemodule/services/TagOptionsPanel.form +++ b/Core/src/org/sleuthkit/autopsy/tags/TagOptionsPanel.form @@ -145,7 +145,7 @@ - + @@ -358,4 +358,4 @@ - + \ No newline at end of file diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/services/TagOptionsPanel.java b/Core/src/org/sleuthkit/autopsy/tags/TagOptionsPanel.java similarity index 99% rename from Core/src/org/sleuthkit/autopsy/casemodule/services/TagOptionsPanel.java rename to Core/src/org/sleuthkit/autopsy/tags/TagOptionsPanel.java index 2ef9869adc..d92e8e0adc 100755 --- a/Core/src/org/sleuthkit/autopsy/casemodule/services/TagOptionsPanel.java +++ b/Core/src/org/sleuthkit/autopsy/tags/TagOptionsPanel.java @@ -16,7 +16,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.sleuthkit.autopsy.casemodule.services; +package org.sleuthkit.autopsy.tags; import java.awt.EventQueue; import java.beans.PropertyChangeEvent; @@ -382,7 +382,7 @@ final class TagOptionsPanel extends javax.swing.JPanel implements OptionsPanel { private javax.swing.JLabel notableYesOrNoLabel; private javax.swing.JScrollPane panelDescriptionScrollPane; private javax.swing.JTextArea panelDescriptionTextArea; - private javax.swing.JList tagNamesList; + private javax.swing.JList tagNamesList; private javax.swing.JPanel tagTypesAdditionalPanel; private javax.swing.JLabel tagTypesListLabel; // End of variables declaration//GEN-END:variables diff --git a/Core/src/org/sleuthkit/autopsy/tags/TagUtilities.java b/Core/src/org/sleuthkit/autopsy/tags/TagUtilities.java new file mode 100755 index 0000000000..d3fb6352b9 --- /dev/null +++ b/Core/src/org/sleuthkit/autopsy/tags/TagUtilities.java @@ -0,0 +1,69 @@ +/* + * Autopsy Forensic Browser + * + * Copyright 2020 Basis Technology Corp. + * Contact: carrier sleuthkit 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.tags; + +import java.util.logging.Level; +import org.sleuthkit.autopsy.coreutils.Logger; +import org.sleuthkit.datamodel.TagName; +import org.sleuthkit.datamodel.TagSet; +import org.sleuthkit.datamodel.TskCoreException; +import org.sleuthkit.datamodel.TskData; + +/** + * + * Utility methods for Tags. + */ +public class TagUtilities { + + private static final Logger logger = Logger.getLogger(TagUtilities.class.getName()); + + private TagUtilities() { + // Intentionally empty constructor; + } + + /** + * Returns a decorated name for the TagName that includes, if available, the + * TagName's TagSet name and notability. + * + * If an exception is throw while trying to retrieve the TagName's TagSet + * the TagSet name will not be included. + * + * @param tagName The TagName value generate name for. + * + * @return The decorated name for the TagName or the TagName display name + * value if an exception occurred. + */ + public static String getDecoratedTagDisplayName(TagName tagName) { + String displayName = tagName.getDisplayName(); + try { + TagSet tagSet = tagName.getTagSet(); + if (tagSet != null) { + displayName = tagSet.getName() + ": " + displayName; + } + } catch (TskCoreException ex) { + logger.log(Level.WARNING, String.format("Failed to get TagSet for TagName (%d)", tagName.getId())); + } + + if (tagName.getKnownStatus() == TskData.FileKnown.BAD) { + displayName += " (Notable)"; + } + + return displayName; + } +} diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/services/TagsOptionsPanelController.java b/Core/src/org/sleuthkit/autopsy/tags/TagsOptionsPanelController.java similarity index 96% rename from Core/src/org/sleuthkit/autopsy/casemodule/services/TagsOptionsPanelController.java rename to Core/src/org/sleuthkit/autopsy/tags/TagsOptionsPanelController.java index 8fa16928d4..241823d987 100644 --- a/Core/src/org/sleuthkit/autopsy/casemodule/services/TagsOptionsPanelController.java +++ b/Core/src/org/sleuthkit/autopsy/tags/TagsOptionsPanelController.java @@ -16,7 +16,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.sleuthkit.autopsy.casemodule.services; +package org.sleuthkit.autopsy.tags; import java.beans.PropertyChangeEvent; import java.beans.PropertyChangeListener; @@ -28,7 +28,7 @@ import org.openide.util.Lookup; @OptionsPanelController.TopLevelRegistration( categoryName = "#OptionsCategory_Name_TagNamesOptions", - iconBase = "org/sleuthkit/autopsy/casemodule/services/tag-options-panel-icon.png", + iconBase = "org/sleuthkit/autopsy/tags/tag-options-panel-icon.png", keywords = "#OptionsCategory_TagNames", keywordsCategory = "CustomTagNames", position = 12 diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/services/tag-options-panel-icon.png b/Core/src/org/sleuthkit/autopsy/tags/tag-options-panel-icon.png similarity index 100% rename from Core/src/org/sleuthkit/autopsy/casemodule/services/tag-options-panel-icon.png rename to Core/src/org/sleuthkit/autopsy/tags/tag-options-panel-icon.png diff --git a/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/datamodel/DrawableTagsManager.java b/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/datamodel/DrawableTagsManager.java index abf2c02586..e75f380a1f 100644 --- a/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/datamodel/DrawableTagsManager.java +++ b/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/datamodel/DrawableTagsManager.java @@ -75,8 +75,8 @@ public final class DrawableTagsManager { public DrawableTagsManager(ImageGalleryController controller) throws TskCoreException { this.autopsyTagsManager = controller.getCase().getServices().getTagsManager(); - followUpTagName = getTagName(TagsManager.getFollowUpDisplayString()); - bookmarkTagName = getTagName(TagsManager.getBookmarkDisplayString()); + followUpTagName = getTagName(TagsManager.getFollowUpTagDisplayName()); + bookmarkTagName = getTagName(TagsManager.getBookmarkTagDisplayName()); this.controller = controller; compareByDisplayName = new Comparator() {