diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/services/Bundle.properties b/Core/src/org/sleuthkit/autopsy/casemodule/services/Bundle.properties old mode 100644 new mode 100755 diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/services/Bundle.properties-MERGED b/Core/src/org/sleuthkit/autopsy/casemodule/services/Bundle.properties-MERGED index 5e79318334..8fa5d9888b 100755 --- a/Core/src/org/sleuthkit/autopsy/casemodule/services/Bundle.properties-MERGED +++ b/Core/src/org/sleuthkit/autopsy/casemodule/services/Bundle.properties-MERGED @@ -1,3 +1,9 @@ +Category.five=CAT-5: Non-pertinent +Category.four=CAT-4: Exemplar/Comparison (Internal Use Only) +Category.one=CAT-1: Child Exploitation (Illegal) +Category.three=CAT-3: CGI/Animation (Child Exploitive) +Category.two=CAT-2: Child Exploitation (Non-Illegal/Age Difficult) +Category.zero=CAT-0: Uncategorized OptionsCategory_Name_TagNamesOptions=Tags OptionsCategory_TagNames=TagNames TagNameDefinition.predefTagNames.bookmark.text=Bookmark diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/services/TagNameDefinition.java b/Core/src/org/sleuthkit/autopsy/casemodule/services/TagNameDefinition.java old mode 100644 new mode 100755 index 33e8f29237..b86735a565 --- a/Core/src/org/sleuthkit/autopsy/casemodule/services/TagNameDefinition.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/services/TagNameDefinition.java @@ -20,8 +20,11 @@ package org.sleuthkit.autopsy.casemodule.services; import java.util.ArrayList; import java.util.Arrays; +import java.util.Collections; +import java.util.HashMap; import java.util.LinkedHashSet; import java.util.List; +import java.util.Map; import java.util.Objects; import java.util.Set; import java.util.logging.Level; @@ -32,7 +35,6 @@ import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException; import org.sleuthkit.autopsy.coreutils.Logger; import org.sleuthkit.autopsy.coreutils.ModuleSettings; import org.sleuthkit.datamodel.TagName; -import org.sleuthkit.autopsy.datamodel.DhsImageCategory; import org.sleuthkit.datamodel.SleuthkitCase; import org.sleuthkit.datamodel.TskCoreException; import org.sleuthkit.datamodel.TskData; @@ -46,20 +48,43 @@ final class TagNameDefinition implements Comparable { private static final Logger LOGGER = Logger.getLogger(TagNameDefinition.class.getName()); @NbBundle.Messages({"TagNameDefinition.predefTagNames.bookmark.text=Bookmark", "TagNameDefinition.predefTagNames.followUp.text=Follow Up", - "TagNameDefinition.predefTagNames.notableItem.text=Notable Item"}) - private static final String TAGS_SETTINGS_NAME = "Tags"; //NON-NLS - private static final String TAG_NAMES_SETTING_KEY = "TagNames"; //NON-NLS + "TagNameDefinition.predefTagNames.notableItem.text=Notable Item", + "Category.one=CAT-1: Child Exploitation (Illegal)", + "Category.two=CAT-2: Child Exploitation (Non-Illegal/Age Difficult)", + "Category.three=CAT-3: CGI/Animation (Child Exploitive)", + "Category.four=CAT-4: Exemplar/Comparison (Internal Use Only)", + "Category.five=CAT-5: Non-pertinent", + "Category.zero=CAT-0: Uncategorized"}) + + private static final String TAGS_SETTINGS_NAME = "Tags"; //NON-NLS + private static final String TAG_NAMES_SETTING_KEY = "TagNames"; //NON-NLS + private static final String TAG_NAMES_SETTING_VERSION_KEY = "CustomTagNameVersion"; + private static final String TAG_SETTINGS_NAME_VERSION = "1"; - private static final List STANDARD_NOTABLE_TAG_DISPLAY_NAMES = Arrays.asList(Bundle.TagNameDefinition_predefTagNames_notableItem_text(), DhsImageCategory.ONE.getDisplayName(), DhsImageCategory.TWO.getDisplayName(), DhsImageCategory.THREE.getDisplayName()); // NON-NLS - private static final List STANDARD_TAG_DISPLAY_NAMES = Arrays.asList(Bundle.TagNameDefinition_predefTagNames_bookmark_text(), Bundle.TagNameDefinition_predefTagNames_followUp_text(), - Bundle.TagNameDefinition_predefTagNames_notableItem_text(), DhsImageCategory.ONE.getDisplayName(), - DhsImageCategory.TWO.getDisplayName(), DhsImageCategory.THREE.getDisplayName(), - DhsImageCategory.FOUR.getDisplayName(), DhsImageCategory.FIVE.getDisplayName(), DhsImageCategory.ZERO.getDisplayName()); private final String displayName; private final String description; private final TagName.HTML_COLOR color; private final TskData.FileKnown knownStatus; + static final Map STANDARD_TAGS = new HashMap<>(); + static final Map PROJECT_VIC_DEFAULT_TAGS = new HashMap<>(); + private static final List STANDARD_TAG_NAMES = new ArrayList<>(); + + static { + STANDARD_TAGS.put(Bundle.TagNameDefinition_predefTagNames_bookmark_text(), new TagNameDefinition(Bundle.TagNameDefinition_predefTagNames_bookmark_text(), "", TagName.HTML_COLOR.NONE, TskData.FileKnown.UNKNOWN)); + STANDARD_TAGS.put(Bundle.TagNameDefinition_predefTagNames_followUp_text(), new TagNameDefinition(Bundle.TagNameDefinition_predefTagNames_followUp_text(), "", TagName.HTML_COLOR.NONE, TskData.FileKnown.UNKNOWN)); + STANDARD_TAGS.put(Bundle.TagNameDefinition_predefTagNames_notableItem_text(), new TagNameDefinition(Bundle.TagNameDefinition_predefTagNames_notableItem_text(), "", TagName.HTML_COLOR.NONE, TskData.FileKnown.BAD)); + + PROJECT_VIC_DEFAULT_TAGS.put(Bundle.Category_one(), new TagNameDefinition(Bundle.Category_one(), "", TagName.HTML_COLOR.RED, TskData.FileKnown.BAD)); + PROJECT_VIC_DEFAULT_TAGS.put(Bundle.Category_two(), new TagNameDefinition(Bundle.Category_two(), "", TagName.HTML_COLOR.LIME, TskData.FileKnown.BAD)); + PROJECT_VIC_DEFAULT_TAGS.put(Bundle.Category_three(), new TagNameDefinition(Bundle.Category_three(), "", TagName.HTML_COLOR.YELLOW, TskData.FileKnown.BAD)); + PROJECT_VIC_DEFAULT_TAGS.put(Bundle.Category_four(), new TagNameDefinition(Bundle.Category_four(), "", TagName.HTML_COLOR.PURPLE, TskData.FileKnown.UNKNOWN)); + PROJECT_VIC_DEFAULT_TAGS.put(Bundle.Category_five(), new TagNameDefinition(Bundle.Category_five(), "", TagName.HTML_COLOR.SILVER, TskData.FileKnown.UNKNOWN)); + + STANDARD_TAG_NAMES.addAll(STANDARD_TAGS.keySet()); + STANDARD_TAG_NAMES.addAll(PROJECT_VIC_DEFAULT_TAGS.keySet()); + } + /** * Constructs a tag name definition consisting of a display name, * description, color and knownStatus. @@ -77,7 +102,7 @@ final class TagNameDefinition implements Comparable { } static List getStandardTagNames() { - return STANDARD_TAG_DISPLAY_NAMES; + return Collections.unmodifiableList(STANDARD_TAG_NAMES); } /** @@ -199,7 +224,6 @@ final class TagNameDefinition implements Comparable { static synchronized Set getTagNameDefinitions() { Set tagNames = new LinkedHashSet<>(); //modifiable copy of default tags list for us to keep track of which default tags have already been created - Set standardTags = new LinkedHashSet<>(STANDARD_TAG_DISPLAY_NAMES); String setting = ModuleSettings.getConfigSetting(TAGS_SETTINGS_NAME, TAG_NAMES_SETTING_KEY); if (null != setting && !setting.isEmpty()) { List tagNameTuples = Arrays.asList(setting.split(";")); @@ -210,18 +234,11 @@ final class TagNameDefinition implements Comparable { } if (numberOfAttributes == 3) { // Upgrade Tags.Properties with the settings in Central Repository Settings if necessary - tagNames.addAll(upgradeTagPropertiesFile(tagNameTuples, standardTags)); + tagNames.addAll(upgradeTagPropertiesFile(tagNameTuples)); } else if (numberOfAttributes == 4) { // if the Tags.Properties file is up to date parse it - tagNames.addAll(readCurrentTagPropertiesFile(tagNameTuples, standardTags)); - } - } - //create standard tags which should always exist which were not already created for whatever reason, such as upgrade - for (String standardTagName : standardTags) { - if (STANDARD_NOTABLE_TAG_DISPLAY_NAMES.contains(standardTagName)) { - tagNames.add(new TagNameDefinition(standardTagName, "", TagName.HTML_COLOR.NONE, TskData.FileKnown.BAD)); - } else { - tagNames.add(new TagNameDefinition(standardTagName, "", TagName.HTML_COLOR.NONE, TskData.FileKnown.UNKNOWN)); + Set tagNameDefinitions = readCurrentTagPropertiesFile(tagNameTuples); + tagNames.addAll(tagNameDefinitions); } } return tagNames; @@ -239,24 +256,24 @@ final class TagNameDefinition implements Comparable { * * @return tagNames a list of TagNameDefinitions */ - private static Set upgradeTagPropertiesFile(List tagProperties, Set standardTagsToBeCreated) { + private static Set upgradeTagPropertiesFile(List tagProperties) { Set tagNames = new LinkedHashSet<>(); List legacyNotableTags = new ArrayList<>(); String badTagsStr = ModuleSettings.getConfigSetting("CentralRepository", "db.badTags"); // NON-NLS - if (badTagsStr == null || badTagsStr.isEmpty()) { //if there were no bad tags in the central repo properties file use the default list - legacyNotableTags.addAll(STANDARD_NOTABLE_TAG_DISPLAY_NAMES); - } else { //otherwise use the list that was in the central repository properties file + if (badTagsStr != null && !badTagsStr.isEmpty()) { legacyNotableTags.addAll(Arrays.asList(badTagsStr.split(","))); } + for (String tagNameTuple : tagProperties) { String[] tagNameAttributes = tagNameTuple.split(","); //get the attributes - standardTagsToBeCreated.remove(tagNameAttributes[0]); //remove the tag from the list of standard tags which have not been created - if (legacyNotableTags.contains(tagNameAttributes[0])) { //if tag should be notable mark create it as such - tagNames.add(new TagNameDefinition(tagNameAttributes[0], tagNameAttributes[1], - TagName.HTML_COLOR.valueOf(tagNameAttributes[2]), TskData.FileKnown.BAD)); - } else { //otherwise create it as unknown - tagNames.add(new TagNameDefinition(tagNameAttributes[0], tagNameAttributes[1], - TagName.HTML_COLOR.valueOf(tagNameAttributes[2]), TskData.FileKnown.UNKNOWN)); //add the default value for that tag + if (!(STANDARD_TAGS.containsKey(tagNameAttributes[0]) || PROJECT_VIC_DEFAULT_TAGS.containsKey(tagNameAttributes[0]))) { + if (legacyNotableTags.contains(tagNameAttributes[0])) { //if tag should be notable mark create it as such + tagNames.add(new TagNameDefinition(tagNameAttributes[0], tagNameAttributes[1], + TagName.HTML_COLOR.valueOf(tagNameAttributes[2]), TskData.FileKnown.BAD)); + } else { //otherwise create it as unknown + tagNames.add(new TagNameDefinition(tagNameAttributes[0], tagNameAttributes[1], + TagName.HTML_COLOR.valueOf(tagNameAttributes[2]), TskData.FileKnown.UNKNOWN)); //add the default value for that tag + } } } return tagNames; @@ -264,22 +281,25 @@ final class TagNameDefinition implements Comparable { /** * Read the Tags.properties file to get the TagNameDefinitions that are - * preserved accross cases. + * preserved across cases. * - * @param tagProperties the list of comma seperated tags in the + * @param tagProperties the list of comma separated tags in the * Tags.properties file * @param standardTagsToBeCreated the list of standard tags which have yet * to be created * * @return tagNames a list of TagNameDefinitions */ - private static Set readCurrentTagPropertiesFile(List tagProperties, Set standardTagsToBeCreated) { + private static Set readCurrentTagPropertiesFile(List tagProperties) { Set tagNames = new LinkedHashSet<>(); + String version = ModuleSettings.getConfigSetting(TAGS_SETTINGS_NAME, TAG_SETTINGS_NAME_VERSION); for (String tagNameTuple : tagProperties) { String[] tagNameAttributes = tagNameTuple.split(","); //get the attributes - standardTagsToBeCreated.remove(tagNameAttributes[0]); //remove the tag from the list of standard tags which have not been created - tagNames.add(new TagNameDefinition(tagNameAttributes[0], tagNameAttributes[1], - TagName.HTML_COLOR.valueOf(tagNameAttributes[2]), TskData.FileKnown.valueOf(tagNameAttributes[3]))); + // Remove the standard and project vic tags from this list. + if (version != null || !(STANDARD_TAGS.containsKey(tagNameAttributes[0]) || PROJECT_VIC_DEFAULT_TAGS.containsKey(tagNameAttributes[0]))) { + tagNames.add(new TagNameDefinition(tagNameAttributes[0], tagNameAttributes[1], + TagName.HTML_COLOR.valueOf(tagNameAttributes[2]), TskData.FileKnown.valueOf(tagNameAttributes[3]))); + } } return tagNames; } @@ -303,6 +323,8 @@ final class TagNameDefinition implements Comparable { LOGGER.log(Level.SEVERE, "Exception while getting open case.", ex); } } + + ModuleSettings.setConfigSetting(TAGS_SETTINGS_NAME, TAG_NAMES_SETTING_VERSION_KEY, TAG_SETTINGS_NAME_VERSION); ModuleSettings.setConfigSetting(TAGS_SETTINGS_NAME, TAG_NAMES_SETTING_KEY, setting.toString()); } diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/services/TagNameDialog.java b/Core/src/org/sleuthkit/autopsy/casemodule/services/TagNameDialog.java old mode 100644 new mode 100755 index 79207aaaaa..5b2bb75da5 --- a/Core/src/org/sleuthkit/autopsy/casemodule/services/TagNameDialog.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/services/TagNameDialog.java @@ -140,7 +140,7 @@ final class TagNameDialog extends javax.swing.JDialog { return; } //if a tag name contains illegal characters and is not the name of one of the standard tags - if (TagsManager.containsIllegalCharacters(newTagDisplayName) && !TagNameDefinition.getStandardTagNames().contains(newTagDisplayName)) { + if (TagsManager.containsIllegalCharacters(newTagDisplayName)) { JOptionPane.showMessageDialog(this, NbBundle.getMessage(TagNameDialog.class, "TagNameDialog.JOptionPane.tagDescriptionIllegalCharacters.message"), NbBundle.getMessage(TagNameDialog.class, "TagNameDialog.JOptionPane.tagDescriptionIllegalCharacters.title"), diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/services/TagOptionsPanel.java b/Core/src/org/sleuthkit/autopsy/casemodule/services/TagOptionsPanel.java old mode 100644 new mode 100755 index 4b3aba82a7..0e5ebeb4ea --- a/Core/src/org/sleuthkit/autopsy/casemodule/services/TagOptionsPanel.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/services/TagOptionsPanel.java @@ -446,8 +446,6 @@ final class TagOptionsPanel extends javax.swing.JPanel implements OptionsPanel { boolean isSelected = tagNamesList.getSelectedIndex() != -1; boolean enableEdit = !ingestIsRunning && isSelected; editTagNameButton.setEnabled(enableEdit); - boolean enableDelete = enableEdit && !TagNameDefinition.getStandardTagNames().contains(tagNamesList.getSelectedValue().getDisplayName()); - deleteTagNameButton.setEnabled(enableDelete); if (isSelected) { descriptionTextArea.setText(tagNamesList.getSelectedValue().getDescription()); if (tagNamesList.getSelectedValue().getKnownStatus() == TskData.FileKnown.BAD) { diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/services/TagsManager.java b/Core/src/org/sleuthkit/autopsy/casemodule/services/TagsManager.java old mode 100644 new mode 100755 index 80374dad75..e1487aeda0 --- a/Core/src/org/sleuthkit/autopsy/casemodule/services/TagsManager.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/services/TagsManager.java @@ -41,6 +41,7 @@ import org.sleuthkit.datamodel.ContentTag; import org.sleuthkit.datamodel.SleuthkitCase; import org.sleuthkit.datamodel.TagName; import org.sleuthkit.datamodel.TagSet; +import org.sleuthkit.datamodel.TaggingManager; import org.sleuthkit.datamodel.TskCoreException; import org.sleuthkit.datamodel.TskData; import org.sleuthkit.datamodel.TskData.DbType; @@ -53,9 +54,10 @@ public class TagsManager implements Closeable { private static final Logger LOGGER = Logger.getLogger(TagsManager.class.getName()); private final SleuthkitCase caseDb; - + static { - //Create the contentviewer tags table (beta) if the current case does not + + //Create the contentviewer tags table if the current case does not //have the table present Case.addEventTypeSubscriber(EnumSet.of(Case.Events.CURRENT_CASE), evt -> { if (evt.getNewValue() != null) { @@ -65,7 +67,7 @@ public class TagsManager implements Closeable { if (caseDb.tableExists(ContentViewerTagManager.TABLE_NAME)) { return; } - + if (currentCase.getSleuthkitCase().getDatabaseType().equals(DbType.SQLITE)) { caseDb.createTable(ContentViewerTagManager.TABLE_NAME, ContentViewerTagManager.TABLE_SCHEMA_SQLITE); } else if (currentCase.getSleuthkitCase().getDatabaseType().equals(DbType.POSTGRESQL)) { @@ -169,6 +171,28 @@ public class TagsManager implements Closeable { */ TagsManager(SleuthkitCase caseDb) { this.caseDb = caseDb; + + // Add standard tags and the Project VIC default tag set and tags. + TaggingManager taggingMgr = caseDb.getTagsManager(); + try { + List setList = taggingMgr.getTagSets(); + if (setList.isEmpty()) { + //Assume new case and add Project VIC tags. + TagSet set = taggingMgr.addTagSet("Project VIC (United States)"); + + for (TagNameDefinition def : TagNameDefinition.PROJECT_VIC_DEFAULT_TAGS.values()) { + TagName tagName = caseDb.addOrUpdateTagName(def.getDisplayName(), def.getDescription(), def.getColor(), def.getKnownStatus()); + taggingMgr.addTagNameToTagSet(set, tagName); + } + + for (TagNameDefinition def : TagNameDefinition.STANDARD_TAGS.values()) { + caseDb.addOrUpdateTagName(def.getDisplayName(), def.getDescription(), def.getColor(), def.getKnownStatus()); + } + } + } catch (TskCoreException ex) { + LOGGER.log(Level.SEVERE, "Error updating non-file object ", ex); + } + for (TagNameDefinition tagName : TagNameDefinition.getTagNameDefinitions()) { tagName.saveToCase(caseDb); } @@ -243,7 +267,8 @@ public class TagsManager implements Closeable { /** * Selects all of the rows from the tag_names table in the case database for * which there is at least one matching row in the content_tags or - * blackboard_artifact_tags tables, for the given data source object id and user. + * blackboard_artifact_tags tables, for the given data source object id and + * user. * * @param dsObjId data source object id * @param userName - the user name that you want to get tags for @@ -269,10 +294,6 @@ public class TagsManager implements Closeable { } return new ArrayList<>(tagNameSet); } - - public List getTagSets() { - return null; - } /** * Gets a map of tag display names to tag name entries in the case database. @@ -454,14 +475,19 @@ public class TagsManager implements Closeable { * database. */ public ContentTag addContentTag(Content content, TagName tagName, String comment, long beginByteOffset, long endByteOffset) throws TskCoreException { - ContentTag tag; - tag = caseDb.addContentTag(content, tagName, comment, beginByteOffset, endByteOffset); + TaggingManager.ContentTagChange tagChange = caseDb.getTagsManager().addContentTag(content, tagName, comment, beginByteOffset, endByteOffset); try { - Case.getCurrentCaseThrows().notifyContentTagAdded(tag); + Case currentCase = Case.getCurrentCaseThrows(); + + for (ContentTag tag : tagChange.getRemovedTags()) { + currentCase.notifyContentTagDeleted(tag); + } + + currentCase.notifyContentTagAdded(tagChange.getAddedTag()); } catch (NoCurrentCaseException ex) { throw new TskCoreException("Added a tag to a closed case", ex); } - return tag; + return tagChange.getAddedTag(); } /** @@ -673,13 +699,18 @@ public class TagsManager implements Closeable { * database. */ public BlackboardArtifactTag addBlackboardArtifactTag(BlackboardArtifact artifact, TagName tagName, String comment) throws TskCoreException { - BlackboardArtifactTag tag = caseDb.addBlackboardArtifactTag(artifact, tagName, comment); + TaggingManager.BlackboardArtifactTagChange tagChange = caseDb.getTagsManager().addArtifactTag(artifact, tagName, comment); try { - Case.getCurrentCaseThrows().notifyBlackBoardArtifactTagAdded(tag); + Case currentCase = Case.getCurrentCaseThrows(); + + for (BlackboardArtifactTag tag : tagChange.getRemovedTags()) { + currentCase.notifyBlackBoardArtifactTagDeleted(tag); + } + currentCase.notifyBlackBoardArtifactTagAdded(tagChange.getAddedTag()); } catch (NoCurrentCaseException ex) { throw new TskCoreException("Added a tag to a closed case", ex); } - return tag; + return tagChange.getAddedTag(); } /** diff --git a/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/datamodel/DrawableTagsManager.java b/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/datamodel/DrawableTagsManager.java index 3a9ae712b8..d2cdc484ce 100644 --- a/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/datamodel/DrawableTagsManager.java +++ b/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/datamodel/DrawableTagsManager.java @@ -190,7 +190,7 @@ public final class DrawableTagsManager { returnTagName = autopsyTagsManager.getDisplayNamesToTagNamesMap().get(displayName); if (returnTagName != null) { return returnTagName; - } + } throw new TskCoreException("Tag name exists but an error occured in retrieving it", ex); } }