Merge branch 'develop' of https://github.com/sleuthkit/autopsy into 6516-take2-normalize-cr-account

# Conflicts:
#	Core/src/org/sleuthkit/autopsy/centralrepository/persona/Bundle.properties-MERGED
#	Core/src/org/sleuthkit/autopsy/centralrepository/persona/CreatePersonaAccountDialog.java
This commit is contained in:
Raman Arora 2020-07-08 15:25:05 -04:00
commit 63c1a163ea
57 changed files with 928 additions and 362 deletions

View File

@ -2,7 +2,7 @@ Manifest-Version: 1.0
OpenIDE-Module: org.sleuthkit.autopsy.core/10
OpenIDE-Module-Localizing-Bundle: org/sleuthkit/autopsy/core/Bundle.properties
OpenIDE-Module-Layer: org/sleuthkit/autopsy/core/layer.xml
OpenIDE-Module-Implementation-Version: 31
OpenIDE-Module-Implementation-Version: 32
OpenIDE-Module-Requires: org.openide.windows.WindowManager
AutoUpdate-Show-In-Client: true
AutoUpdate-Essential-Module: true

View File

@ -138,5 +138,5 @@ nbm.homepage=http://www.sleuthkit.org/
nbm.module.author=Brian Carrier
nbm.needs.restart=true
source.reference.curator-recipes-2.8.0.jar=release/modules/ext/curator-recipes-2.8.0-sources.jar
spec.version.base=10.19
spec.version.base=10.20

View File

@ -1,7 +1,7 @@
/*
* Autopsy Forensic Browser
*
* Copyright 2011-2019 Basis Technology Corp.
* Copyright 2013-2020 Basis Technology Corp.
* Contact: carrier <at> sleuthkit <dot> org
*
* Licensed under the Apache License, Version 2.0 (the "License");
@ -139,7 +139,7 @@ abstract class AddTagAction extends AbstractAction implements Presenter.Popup {
if (!tagNamesMap.isEmpty()) {
for (Map.Entry<String, TagName> entry : tagNamesMap.entrySet()) {
TagName tagName = entry.getValue();
TagSet tagSet = tagName.getTagSet();
TagSet tagSet = tagsManager.getTagSet(tagName);
// Show custom tags before predefined tags in the menu
if (tagSet != null) {

View File

@ -1,7 +1,7 @@
/*
* Autopsy Forensic Browser
*
* Copyright 2011-2018 Basis Technology Corp.
* Copyright 2013-2020 Basis Technology Corp.
* Contact: carrier <at> sleuthkit <dot> org
*
* Licensed under the Apache License, Version 2.0 (the "License");
@ -23,7 +23,6 @@ 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.logging.Level;
import java.util.List;
import java.util.Map;
@ -36,7 +35,6 @@ import javax.swing.JComponent;
import javax.swing.JDialog;
import javax.swing.JList;
import javax.swing.KeyStroke;
import org.openide.util.Exceptions;
import org.openide.util.NbBundle;
import org.openide.windows.WindowManager;
import org.sleuthkit.autopsy.casemodule.Case;
@ -150,7 +148,7 @@ public class GetTagNameAndCommentDialog extends JDialog {
}
);
try {
try {
TagsManager tagsManager = Case.getCurrentCaseThrows().getServices().getTagsManager();
List<String> standardTagNames = TagsManager.getStandardTagNames();
Map<String, TagName> tagNamesMap = new TreeMap<>(tagsManager.getDisplayNamesToTagNamesMap());
@ -161,7 +159,7 @@ public class GetTagNameAndCommentDialog extends JDialog {
tagNamesMap.entrySet().stream().map((entry) -> entry.getValue()).forEachOrdered((tagName) -> {
TagSet tagSet = null;
try {
tagSet = tagName.getTagSet();
tagSet = tagsManager.getTagSet(tagName);
} catch (TskCoreException ex) {
Logger.getLogger(GetTagNameAndCommentDialog.class
.getName()).log(Level.SEVERE, "Failed to get tag set", ex); //NON-NLS

View File

@ -1,7 +1,7 @@
/*
* Autopsy Forensic Browser
*
* Copyright 2018 Basis Technology Corp.
* Copyright 2018-2020 Basis Technology Corp.
* Contact: carrier <at> sleuthkit <dot> org
*
* Licensed under the Apache License, Version 2.0 (the "License");
@ -131,7 +131,7 @@ abstract class ReplaceTagAction<T extends Tag> extends AbstractAction implements
if (!tagNamesMap.isEmpty()) {
for (Map.Entry<String, TagName> entry : tagNamesMap.entrySet()) {
TagName tagName = entry.getValue();
TagSet tagSet = tagName.getTagSet();
TagSet tagSet = tagsManager.getTagSet(tagName);
// Show custom tags before predefined tags in the menu
if (tagSet != null) {

View File

@ -1,7 +1,7 @@
/*
* Autopsy Forensic Browser
*
* Copyright 2011-2020 Basis Technology Corp.
* Copyright 2013-2020 Basis Technology Corp.
* Contact: carrier <at> sleuthkit <dot> org
*
* Licensed under the Apache License, Version 2.0 (the "License");
@ -56,7 +56,7 @@ public class TagsManager implements Closeable {
private final SleuthkitCase caseDb;
private static String DEFAULT_TAG_SET_NAME = "Project VIC";
private static final Object lock = new Object();
static {
@ -235,16 +235,16 @@ public class TagsManager implements Closeable {
public static String getNotableTagDisplayName() {
return TagNameDefinition.getNotableTagDisplayName();
}
/**
* Creates a new TagSetDefinition file.
*
*
* @param tagSetDef The tag set definition.
*
* @throws IOException
*
* @throws IOException
*/
public static void addTagSetDefinition(TagSetDefinition tagSetDef) throws IOException {
synchronized(lock) {
synchronized (lock) {
TagSetDefinition.writeTagSetDefinition(tagSetDef);
}
}
@ -267,20 +267,20 @@ public class TagsManager implements Closeable {
caseDb.addOrUpdateTagName(def.getDisplayName(), def.getDescription(), def.getColor(), def.getKnownStatus());
}
//Assume new case and add tag sets
for(TagSetDefinition setDef: TagSetDefinition.readTagSetDefinitions()) {
for (TagSetDefinition setDef : TagSetDefinition.readTagSetDefinitions()) {
List<TagName> tagNameList = new ArrayList<>();
for(TagNameDefinition tagNameDef: setDef.getTagNameDefinitions()) {
for (TagNameDefinition tagNameDef : setDef.getTagNameDefinitions()) {
tagNameList.add(caseDb.addOrUpdateTagName(tagNameDef.getDisplayName(), tagNameDef.getDescription(), tagNameDef.getColor(), tagNameDef.getKnownStatus()));
}
if(!tagNameList.isEmpty()) {
if (!tagNameList.isEmpty()) {
taggingMgr.addTagSet(setDef.getName(), tagNameList);
}
}
}
} catch (TskCoreException ex) {
LOGGER.log(Level.SEVERE, "Error updating standard tag name and tag set definitions", ex);
} catch(IOException ex) {
} catch (IOException ex) {
LOGGER.log(Level.SEVERE, "Error loading tag set JSON files", ex);
}
@ -288,28 +288,41 @@ public class TagsManager implements Closeable {
tagName.saveToCase(caseDb);
}
}
/**
* Get a list of all tag sets currently in the case database.
*
*
* @return A list, possibly empty, of TagSet objects.
*
*
* @throws TskCoreException
*/
public List<TagSet> getAllTagSets() throws TskCoreException {
return caseDb.getTaggingManager().getTagSets();
}
/**
* Gets the tag set a tag name (tag definition) belongs to, if any.
*
* @param tagName The tag name.
*
* @return A TagSet object or null.
*
* @throws TskCoreException If there is an error querying the case database.
*/
public TagSet getTagSet(TagName tagName) throws TskCoreException {
return caseDb.getTaggingManager().getTagSet(tagName);
}
/**
* Add a new TagSet to the case database. Tags will be ranked in the order
* which they are passed to this method.
*
* @param name Tag set name.
*
* @param name Tag set name.
* @param tagNameList List of TagName in rank order.
*
*
* @return A new TagSet object.
*
* @throws TskCoreException
*
* @throws TskCoreException
*/
public TagSet addTagSet(String name, List<TagName> tagNameList) throws TskCoreException {
return caseDb.getTaggingManager().addTagSet(name, tagNameList);
@ -501,7 +514,7 @@ public class TagsManager implements Closeable {
* name to the case database.
*/
public TagName addTagName(String displayName, String description, TagName.HTML_COLOR color, TskData.FileKnown knownStatus) throws TagNameAlreadyExistsException, TskCoreException {
synchronized(lock) {
synchronized (lock) {
try {
TagName tagName = caseDb.addOrUpdateTagName(displayName, description, color, knownStatus);
Set<TagNameDefinition> customTypes = TagNameDefinition.getTagNameDefinitions();

View File

@ -255,7 +255,7 @@ public class Persona {
/**
* Sets the comment of this persona.
*
* @param name The new comment.
* @param comment The new comment.
*
* @throws CentralRepoException If there is an error.
*/
@ -313,7 +313,9 @@ public class Persona {
/**
* Modifies the confidence / justification of the given PersonaAccount
*
* @param account account to modify
* @param account Account to modify.
* @param confidence Level of confidence.
* @param justification Justification.
*
* @throws CentralRepoException If there is an error in querying the
* Personas table.
@ -485,7 +487,9 @@ public class Persona {
/**
* Modifies the given alias.
*
* @param alias alias to modify
* @param key Key for the alias to modify.
* @param confidence Level of confidence.
* @param justification Justification.
*
* @throws CentralRepoException If there is an error in querying the
* Personas table.
@ -535,7 +539,9 @@ public class Persona {
/**
* Modifies the given metadata.
*
* @param metadata metadata to modify
* @param key Key for the metadata to modify.
* @param confidence Level of confidence.
* @param justification Justification.
*
* @throws CentralRepoException If there is an error in querying the
* Personas table.

View File

@ -79,3 +79,4 @@ CreatePersonaAccountDialog.typeLbl.text=Type:
CreatePersonaAccountDialog.identifierTextField.text=
CreatePersonaAccountDialog.identiferLbl.text=Identifier:
CreatePersonaAccountDialog.okBtn.text=OK
PersonasTopComponent.introText.text=Personas represent an online identity. They span cases and are stored in the Central Repository based on accounts that were found in artifacts. You can create, edit, and delete personas here.

View File

@ -4,8 +4,10 @@ AddMetadataDialog_dup_Title=Metadata add failure
AddMetadataDialog_empty_name_msg=A metadata entry cannot have an empty name or value.
AddMetadataDialog_empty_name_Title=Missing field(s)
CreatePersonaAccountDialog.title.text=Create Account
CreatePersonaAccountDialog_dup_msg=An account with this identifier and type already exists.
CreatePersonaAccountDialog_dup_Title=Account creation failure
CreatePersonaAccountDialog_error_msg=Failed to create account.
CreatePersonaAccountDialog_error_title=Account failure
CreatePersonaAccountDialog_success_msg=Account added.
CreatePersonaAccountDialog_success_title=Account added
CreatePersonaAccountDialog_invalid_account_msg=Account identifier is not valid.
CreatePersonaAccountDialog_invalid_account_Title=Invalid account identifier
CTL_OpenPersonas=Personas
@ -123,6 +125,7 @@ CreatePersonaAccountDialog.typeLbl.text=Type:
CreatePersonaAccountDialog.identifierTextField.text=
CreatePersonaAccountDialog.identiferLbl.text=Identifier:
CreatePersonaAccountDialog.okBtn.text=OK
PersonasTopComponent.introText.text=Personas represent an online identity. They span cases and are stored in the Central Repository based on accounts that were found in artifacts. You can create, edit, and delete personas here.
PersonasTopComponent_delete_confirmation_msg=Are you sure you want to delete this persona?
PersonasTopComponent_delete_confirmation_Title=Are you sure?
PersonasTopComponent_delete_exception_msg=Failed to delete persona.

View File

@ -214,6 +214,8 @@ public class CreatePersonaAccountDialog extends JDialog {
}
@Messages({
"CreatePersonaAccountDialog_error_title=Account failure",
"CreatePersonaAccountDialog_error_msg=Failed to create account.",
"CreatePersonaAccountDialog_invalid_account_Title=Invalid account identifier",
"CreatePersonaAccountDialog_invalid_account_msg=Account identifier is not valid.",})
private CentralRepoAccount createAccount(CentralRepoAccount.CentralRepoAccountType type, String identifier) {
@ -224,10 +226,10 @@ public class CreatePersonaAccountDialog extends JDialog {
ret = cr.getOrCreateAccount(type, identifier);
}
} catch (CentralRepoException e) {
logger.log(Level.SEVERE, "Failed to access central repository", e);
logger.log(Level.SEVERE, "Failed to create account", e);
JOptionPane.showMessageDialog(this,
Bundle.PersonaAccountDialog_get_types_exception_msg(),
Bundle.PersonaAccountDialog_get_types_exception_Title(),
Bundle.CreatePersonaAccountDialog_error_msg(),
Bundle.CreatePersonaAccountDialog_error_title(),
JOptionPane.ERROR_MESSAGE);
} catch (InvalidAccountIDException e) {
logger.log(Level.WARNING, "Invalid account identifier", e);
@ -240,8 +242,9 @@ public class CreatePersonaAccountDialog extends JDialog {
}
@Messages({
"CreatePersonaAccountDialog_dup_Title=Account creation failure",
"CreatePersonaAccountDialog_dup_msg=An account with this identifier and type already exists.",})
"CreatePersonaAccountDialog_success_title=Account added",
"CreatePersonaAccountDialog_success_msg=Account added.",
})
private void okBtnActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_okBtnActionPerformed
if (identifierTextField.getText().isEmpty()) {
JOptionPane.showMessageDialog(this,
@ -256,6 +259,12 @@ public class CreatePersonaAccountDialog extends JDialog {
String identifier = identifierTextField.getText();
if (createAccount(type, identifier) != null) {
// show account created message
JOptionPane.showMessageDialog(this,
Bundle.CreatePersonaAccountDialog_success_msg(),
Bundle.CreatePersonaAccountDialog_success_title(),
JOptionPane.INFORMATION_MESSAGE);
dispose();
}
}//GEN-LAST:event_okBtnActionPerformed

View File

@ -1,26 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
<!--
Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements. See the NOTICE file
distributed with this work for additional information
regarding copyright ownership. The ASF licenses this file
to you 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.
-->
<Form version="1.5" maxVersion="1.9" type="org.netbeans.modules.form.forminfo.JPanelFormInfo">
<NonVisualComponents>
<Component class="javax.swing.ButtonGroup" name="searchButtonGroup">
@ -44,17 +23,52 @@
<Layout>
<DimensionLayout dim="0">
<Group type="103" groupAlignment="0" attributes="0">
<Component id="jSplitPane1" alignment="0" pref="794" max="32767" attributes="0"/>
<Component id="introTextScrollPane" alignment="0" max="32767" attributes="0"/>
<Component id="mainSplitPane" alignment="0" pref="724" max="32767" attributes="0"/>
</Group>
</DimensionLayout>
<DimensionLayout dim="1">
<Group type="103" groupAlignment="0" attributes="0">
<Component id="jSplitPane1" alignment="0" max="32767" attributes="0"/>
<Group type="102" alignment="1" attributes="0">
<Component id="introTextScrollPane" min="-2" pref="49" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Component id="mainSplitPane" pref="470" max="32767" attributes="0"/>
</Group>
</Group>
</DimensionLayout>
</Layout>
<SubComponents>
<Container class="javax.swing.JSplitPane" name="jSplitPane1">
<Container class="javax.swing.JScrollPane" name="introTextScrollPane">
<Properties>
<Property name="verticalScrollBarPolicy" type="int" value="21"/>
</Properties>
<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.JTextArea" name="introText">
<Properties>
<Property name="background" type="java.awt.Color" editor="org.netbeans.modules.form.RADConnectionPropertyEditor">
<Connection component="Form" name="getBackground" type="method"/>
</Property>
<Property name="columns" type="int" value="20"/>
<Property name="lineWrap" type="boolean" value="true"/>
<Property name="rows" type="int" value="5"/>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/centralrepository/persona/Bundle.properties" key="PersonasTopComponent.introText.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
<Property name="wrapStyleWord" type="boolean" value="true"/>
<Property name="focusable" type="boolean" value="false"/>
</Properties>
</Component>
</SubComponents>
</Container>
<Container class="javax.swing.JSplitPane" name="mainSplitPane">
<Properties>
<Property name="dividerLocation" type="int" value="400"/>
</Properties>
<Layout class="org.netbeans.modules.form.compat2.layouts.support.JSplitPaneSupportLayout"/>
<SubComponents>
@ -71,14 +85,7 @@
<Group type="102" alignment="0" attributes="0">
<EmptySpace max="-2" attributes="0"/>
<Group type="103" groupAlignment="0" attributes="0">
<Component id="jSeparator1" max="32767" attributes="0"/>
<Group type="102" alignment="0" attributes="0">
<Component id="createBtn" min="-2" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Component id="editBtn" min="-2" max="-2" attributes="0"/>
<EmptySpace max="32767" attributes="0"/>
<Component id="deleteBtn" min="-2" max="-2" attributes="0"/>
</Group>
<Component id="createButtonSeparator" max="32767" attributes="0"/>
<Component id="resultsPane" pref="0" max="32767" attributes="0"/>
<Component id="searchField" max="32767" attributes="0"/>
<Group type="102" attributes="0">
@ -88,8 +95,17 @@
<EmptySpace max="32767" attributes="0"/>
<Component id="searchBtn" min="-2" max="-2" attributes="0"/>
</Group>
<Group type="102" alignment="0" attributes="0">
<Component id="createAccountBtn" min="-2" max="-2" attributes="0"/>
<Group type="102" attributes="0">
<Group type="103" groupAlignment="0" attributes="0">
<Component id="createAccountBtn" min="-2" max="-2" attributes="0"/>
<Group type="102" alignment="0" attributes="0">
<Component id="createBtn" min="-2" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Component id="editBtn" min="-2" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Component id="deleteBtn" min="-2" max="-2" attributes="0"/>
</Group>
</Group>
<EmptySpace min="0" pref="0" max="32767" attributes="0"/>
</Group>
</Group>
@ -109,7 +125,7 @@
<Component id="searchBtn" alignment="3" min="-2" max="-2" attributes="0"/>
</Group>
<EmptySpace max="-2" attributes="0"/>
<Component id="resultsPane" pref="457" max="32767" attributes="0"/>
<Component id="resultsPane" pref="300" max="32767" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Group type="103" groupAlignment="3" attributes="0">
<Component id="editBtn" alignment="3" min="-2" max="-2" attributes="0"/>
@ -117,7 +133,7 @@
<Component id="deleteBtn" alignment="3" min="-2" max="-2" attributes="0"/>
</Group>
<EmptySpace max="-2" attributes="0"/>
<Component id="jSeparator1" min="-2" pref="4" max="-2" attributes="0"/>
<Component id="createButtonSeparator" min="-2" pref="4" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Component id="createAccountBtn" min="-2" pref="32" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
@ -154,6 +170,13 @@
</Property>
</Properties>
</Component>
<Component class="javax.swing.JButton" name="searchBtn">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/centralrepository/persona/Bundle.properties" key="PersonasTopComponent.searchBtn.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
</Properties>
</Component>
<Container class="javax.swing.JScrollPane" name="resultsPane">
<AuxValues>
<AuxValue name="autoScrollPane" type="java.lang.Boolean" value="true"/>
@ -191,13 +214,6 @@
</Component>
</SubComponents>
</Container>
<Component class="javax.swing.JButton" name="searchBtn">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/centralrepository/persona/Bundle.properties" key="PersonasTopComponent.searchBtn.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
</Properties>
</Component>
<Component class="javax.swing.JButton" name="createAccountBtn">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
@ -208,16 +224,6 @@
<AuxValue name="generateMnemonicsCode" type="java.lang.Boolean" value="true"/>
</AuxValues>
</Component>
<Component class="javax.swing.JButton" name="createBtn">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/centralrepository/persona/Bundle.properties" key="PersonasTopComponent.createBtn.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
</Properties>
<AuxValues>
<AuxValue name="generateMnemonicsCode" type="java.lang.Boolean" value="true"/>
</AuxValues>
</Component>
<Component class="javax.swing.JButton" name="editBtn">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
@ -234,17 +240,33 @@
<Property name="enabled" type="boolean" value="false"/>
</Properties>
</Component>
<Component class="javax.swing.JSeparator" name="jSeparator1">
<Component class="javax.swing.JSeparator" name="createButtonSeparator">
</Component>
<Component class="javax.swing.JButton" name="createBtn">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/centralrepository/persona/Bundle.properties" key="PersonasTopComponent.createBtn.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
</Properties>
<AuxValues>
<AuxValue name="generateMnemonicsCode" type="java.lang.Boolean" value="true"/>
</AuxValues>
</Component>
</SubComponents>
</Container>
<Component class="org.sleuthkit.autopsy.centralrepository.persona.PersonaDetailsPanel" name="detailsPanel">
<Container class="javax.swing.JScrollPane" name="detailsScrollPane">
<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>
</Component>
<Layout class="org.netbeans.modules.form.compat2.layouts.support.JScrollPaneSupportLayout"/>
<SubComponents>
<Component class="org.sleuthkit.autopsy.centralrepository.persona.PersonaDetailsPanel" name="detailsPanel">
</Component>
</SubComponents>
</Container>
</SubComponents>
</Container>
</SubComponents>

View File

@ -263,23 +263,39 @@ public final class PersonasTopComponent extends TopComponent {
private void initComponents() {
searchButtonGroup = new javax.swing.ButtonGroup();
jSplitPane1 = new javax.swing.JSplitPane();
introTextScrollPane = new javax.swing.JScrollPane();
introText = new javax.swing.JTextArea();
mainSplitPane = new javax.swing.JSplitPane();
searchPanel = new javax.swing.JPanel();
searchField = new javax.swing.JTextField();
searchNameRadio = new javax.swing.JRadioButton();
searchAccountRadio = new javax.swing.JRadioButton();
searchBtn = new javax.swing.JButton();
resultsPane = new javax.swing.JScrollPane();
resultsTable = new javax.swing.JTable();
searchBtn = new javax.swing.JButton();
createAccountBtn = new javax.swing.JButton();
createBtn = new javax.swing.JButton();
editBtn = new javax.swing.JButton();
deleteBtn = new javax.swing.JButton();
jSeparator1 = new javax.swing.JSeparator();
createButtonSeparator = new javax.swing.JSeparator();
createBtn = new javax.swing.JButton();
detailsScrollPane = new javax.swing.JScrollPane();
detailsPanel = new org.sleuthkit.autopsy.centralrepository.persona.PersonaDetailsPanel();
setName(""); // NOI18N
introTextScrollPane.setVerticalScrollBarPolicy(javax.swing.ScrollPaneConstants.VERTICAL_SCROLLBAR_NEVER);
introText.setBackground(getBackground());
introText.setColumns(20);
introText.setLineWrap(true);
introText.setRows(5);
introText.setText(org.openide.util.NbBundle.getMessage(PersonasTopComponent.class, "PersonasTopComponent.introText.text")); // NOI18N
introText.setWrapStyleWord(true);
introText.setFocusable(false);
introTextScrollPane.setViewportView(introText);
mainSplitPane.setDividerLocation(400);
searchField.setText(org.openide.util.NbBundle.getMessage(PersonasTopComponent.class, "PersonasTopComponent.searchField.text")); // NOI18N
searchButtonGroup.add(searchNameRadio);
@ -289,6 +305,8 @@ public final class PersonasTopComponent extends TopComponent {
searchButtonGroup.add(searchAccountRadio);
org.openide.awt.Mnemonics.setLocalizedText(searchAccountRadio, org.openide.util.NbBundle.getMessage(PersonasTopComponent.class, "PersonasTopComponent.searchAccountRadio.text")); // NOI18N
org.openide.awt.Mnemonics.setLocalizedText(searchBtn, org.openide.util.NbBundle.getMessage(PersonasTopComponent.class, "PersonasTopComponent.searchBtn.text")); // NOI18N
resultsTable.setToolTipText(org.openide.util.NbBundle.getMessage(PersonasTopComponent.class, "PersonasTopComponent.resultsTable.toolTipText")); // NOI18N
resultsTable.getTableHeader().setReorderingAllowed(false);
resultsPane.setViewportView(resultsTable);
@ -298,18 +316,16 @@ public final class PersonasTopComponent extends TopComponent {
resultsTable.getColumnModel().getColumn(1).setHeaderValue(org.openide.util.NbBundle.getMessage(PersonasTopComponent.class, "PersonasTopComponent.resultsTable.columnModel.title1")); // NOI18N
}
org.openide.awt.Mnemonics.setLocalizedText(searchBtn, org.openide.util.NbBundle.getMessage(PersonasTopComponent.class, "PersonasTopComponent.searchBtn.text")); // NOI18N
org.openide.awt.Mnemonics.setLocalizedText(createAccountBtn, org.openide.util.NbBundle.getMessage(PersonasTopComponent.class, "PersonasTopComponent.createAccountBtn.text")); // NOI18N
org.openide.awt.Mnemonics.setLocalizedText(createBtn, org.openide.util.NbBundle.getMessage(PersonasTopComponent.class, "PersonasTopComponent.createBtn.text")); // NOI18N
org.openide.awt.Mnemonics.setLocalizedText(editBtn, org.openide.util.NbBundle.getMessage(PersonasTopComponent.class, "PersonasTopComponent.editBtn.text")); // NOI18N
editBtn.setEnabled(false);
org.openide.awt.Mnemonics.setLocalizedText(deleteBtn, org.openide.util.NbBundle.getMessage(PersonasTopComponent.class, "PersonasTopComponent.deleteBtn.text")); // NOI18N
deleteBtn.setEnabled(false);
org.openide.awt.Mnemonics.setLocalizedText(createBtn, org.openide.util.NbBundle.getMessage(PersonasTopComponent.class, "PersonasTopComponent.createBtn.text")); // NOI18N
javax.swing.GroupLayout searchPanelLayout = new javax.swing.GroupLayout(searchPanel);
searchPanel.setLayout(searchPanelLayout);
searchPanelLayout.setHorizontalGroup(
@ -317,13 +333,7 @@ public final class PersonasTopComponent extends TopComponent {
.addGroup(searchPanelLayout.createSequentialGroup()
.addContainerGap()
.addGroup(searchPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(jSeparator1)
.addGroup(searchPanelLayout.createSequentialGroup()
.addComponent(createBtn)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(editBtn)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addComponent(deleteBtn))
.addComponent(createButtonSeparator)
.addComponent(resultsPane, javax.swing.GroupLayout.PREFERRED_SIZE, 0, Short.MAX_VALUE)
.addComponent(searchField)
.addGroup(searchPanelLayout.createSequentialGroup()
@ -333,7 +343,14 @@ public final class PersonasTopComponent extends TopComponent {
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addComponent(searchBtn))
.addGroup(searchPanelLayout.createSequentialGroup()
.addComponent(createAccountBtn)
.addGroup(searchPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(createAccountBtn)
.addGroup(searchPanelLayout.createSequentialGroup()
.addComponent(createBtn)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(editBtn)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(deleteBtn)))
.addGap(0, 0, Short.MAX_VALUE)))
.addContainerGap())
);
@ -348,42 +365,52 @@ public final class PersonasTopComponent extends TopComponent {
.addComponent(searchAccountRadio)
.addComponent(searchBtn))
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(resultsPane, javax.swing.GroupLayout.DEFAULT_SIZE, 457, Short.MAX_VALUE)
.addComponent(resultsPane, javax.swing.GroupLayout.DEFAULT_SIZE, 300, Short.MAX_VALUE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addGroup(searchPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
.addComponent(editBtn)
.addComponent(createBtn)
.addComponent(deleteBtn))
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(jSeparator1, javax.swing.GroupLayout.PREFERRED_SIZE, 4, javax.swing.GroupLayout.PREFERRED_SIZE)
.addComponent(createButtonSeparator, javax.swing.GroupLayout.PREFERRED_SIZE, 4, javax.swing.GroupLayout.PREFERRED_SIZE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(createAccountBtn, javax.swing.GroupLayout.PREFERRED_SIZE, 32, javax.swing.GroupLayout.PREFERRED_SIZE)
.addContainerGap())
);
jSplitPane1.setLeftComponent(searchPanel);
jSplitPane1.setRightComponent(detailsPanel);
mainSplitPane.setLeftComponent(searchPanel);
detailsScrollPane.setViewportView(detailsPanel);
mainSplitPane.setRightComponent(detailsScrollPane);
javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
this.setLayout(layout);
layout.setHorizontalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(jSplitPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 794, Short.MAX_VALUE)
.addComponent(introTextScrollPane)
.addComponent(mainSplitPane, javax.swing.GroupLayout.DEFAULT_SIZE, 724, Short.MAX_VALUE)
);
layout.setVerticalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(jSplitPane1)
.addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
.addComponent(introTextScrollPane, javax.swing.GroupLayout.PREFERRED_SIZE, 49, javax.swing.GroupLayout.PREFERRED_SIZE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(mainSplitPane, javax.swing.GroupLayout.DEFAULT_SIZE, 470, Short.MAX_VALUE))
);
}// </editor-fold>//GEN-END:initComponents
// Variables declaration - do not modify//GEN-BEGIN:variables
private javax.swing.JButton createAccountBtn;
private javax.swing.JButton createBtn;
private javax.swing.JSeparator createButtonSeparator;
private javax.swing.JButton deleteBtn;
private org.sleuthkit.autopsy.centralrepository.persona.PersonaDetailsPanel detailsPanel;
private javax.swing.JScrollPane detailsScrollPane;
private javax.swing.JButton editBtn;
private javax.swing.JSeparator jSeparator1;
private javax.swing.JSplitPane jSplitPane1;
private javax.swing.JTextArea introText;
private javax.swing.JScrollPane introTextScrollPane;
private javax.swing.JSplitPane mainSplitPane;
private javax.swing.JScrollPane resultsPane;
private javax.swing.JTable resultsTable;
private javax.swing.JRadioButton searchAccountRadio;

View File

@ -17,7 +17,7 @@ ContactsViewer_columnHeader_Phone=Phone
ContactsViewer_noContacts_message=<No contacts found for selected account>
ContactsViewer_tabTitle=Contacts
MediaViewer_Name=Media Attachments
MessageNode_Node_Property_Attms=Attachments
MessageNode_Node_Property_Attms=Attachment Count
MessageNode_Node_Property_Date=Date
MessageNode_Node_Property_From=From
MessageNode_Node_Property_Subject=Subject

View File

@ -48,22 +48,22 @@ import org.sleuthkit.datamodel.blackboardutils.attributes.MessageAttachments;
class MessageNode extends BlackboardArtifactNode {
public static final String UNTHREADED_ID = "<UNTHREADED>";
private static final Logger logger = Logger.getLogger(MessageNode.class.getName());
private final String threadID;
private final Action preferredAction;
MessageNode(BlackboardArtifact artifact, String threadID, Action preferredAction) {
MessageNode(BlackboardArtifact artifact, String threadID, Action preferredAction) {
super(artifact);
this.preferredAction = preferredAction;
final String stripEnd = StringUtils.stripEnd(artifact.getDisplayName(), "s"); // NON-NLS
String removeEndIgnoreCase = StringUtils.removeEndIgnoreCase(stripEnd, "message"); // NON-NLS
setDisplayName(removeEndIgnoreCase.isEmpty() ? stripEnd : removeEndIgnoreCase);
this.threadID = threadID;
}
@ -73,12 +73,12 @@ class MessageNode extends BlackboardArtifactNode {
"MessageNode_Node_Property_To=To",
"MessageNode_Node_Property_Date=Date",
"MessageNode_Node_Property_Subject=Subject",
"MessageNode_Node_Property_Attms=Attachments"
"MessageNode_Node_Property_Attms=Attachment Count"
})
@Override
protected Sheet createSheet() {
Sheet sheet = super.createSheet();
Sheet sheet = Sheet.createDefault();
Sheet.Set sheetSet = sheet.get(Sheet.PROPERTIES);
if (sheetSet == null) {
sheetSet = Sheet.createPropertiesSet();
@ -89,42 +89,45 @@ class MessageNode extends BlackboardArtifactNode {
final BlackboardArtifact artifact = getArtifact();
BlackboardArtifact.ARTIFACT_TYPE fromID = BlackboardArtifact.ARTIFACT_TYPE.fromID(artifact.getArtifactTypeID());
if(fromID == null ||
(fromID != TSK_EMAIL_MSG &&
fromID != TSK_MESSAGE)) {
if (fromID == null
|| (fromID != TSK_EMAIL_MSG
&& fromID != TSK_MESSAGE)) {
return sheet;
}
sheetSet.put(new NodeProperty<>("ThreadID", "ThreadID","",threadID == null ? UNTHREADED_ID : threadID)); //NON-NLS
if (threadID != null) {
sheetSet.put(new NodeProperty<>("ThreadID", "ThreadID", "", threadID)); //NON-NLS
}
sheetSet.put(new NodeProperty<>("Subject", Bundle.MessageNode_Node_Property_Subject(), "",
getAttributeDisplayString(artifact, TSK_SUBJECT))); //NON-NLS
getAttributeDisplayString(artifact, TSK_SUBJECT))); //NON-NLS
try {
sheetSet.put(new NodeProperty<>("Attms", Bundle.MessageNode_Node_Property_Attms(), "", getAttachmentsCount())); //NON-NLS
} catch (TskCoreException ex) {
logger.log(Level.WARNING, "Error loading attachment count for " + artifact, ex); //NON-NLS
}
switch (fromID) {
case TSK_EMAIL_MSG:
sheetSet.put(new NodeProperty<>("From", Bundle.MessageNode_Node_Property_From(), "",
StringUtils.strip(getAttributeDisplayString(artifact, TSK_EMAIL_FROM), " \t\n;"))); //NON-NLS
sheetSet.put(new NodeProperty<>("To", Bundle.MessageNode_Node_Property_To(), "",
StringUtils.strip(getAttributeDisplayString(artifact, TSK_EMAIL_TO), " \t\n;"))); //NON-NLS
sheetSet.put(new NodeProperty<>("Date", Bundle.MessageNode_Node_Property_Date(), "",
getAttributeDisplayString(artifact, TSK_DATETIME_SENT))); //NON-NLS
break;
case TSK_MESSAGE:
sheetSet.put(new NodeProperty<>("From", Bundle.MessageNode_Node_Property_From(), "",
getAttributeDisplayString(artifact, TSK_PHONE_NUMBER_FROM))); //NON-NLS
sheetSet.put(new NodeProperty<>("To", Bundle.MessageNode_Node_Property_To(), "",
getAttributeDisplayString(artifact, TSK_PHONE_NUMBER_TO))); //NON-NLS
sheetSet.put(new NodeProperty<>("Date", Bundle.MessageNode_Node_Property_Date(), "",
getAttributeDisplayString(artifact, TSK_DATETIME))); //NON-NLS
break;
default:
break;
String msg_from = getAttributeDisplayString(artifact, TSK_EMAIL_FROM);
String msg_to = getAttributeDisplayString(artifact, TSK_EMAIL_TO);
String date = getAttributeDisplayString(artifact, TSK_DATETIME_SENT);
if (msg_from.isEmpty()) {
msg_from = getAttributeDisplayString(artifact, TSK_PHONE_NUMBER_FROM);
}
if (msg_to.isEmpty()) {
msg_to = getAttributeDisplayString(artifact, TSK_PHONE_NUMBER_TO);
}
if (date.isEmpty()) {
date = getAttributeDisplayString(artifact, TSK_DATETIME);
}
sheetSet.put(new NodeProperty<>("From", Bundle.MessageNode_Node_Property_From(), "",
msg_from)); //NON-NLS
sheetSet.put(new NodeProperty<>("To", Bundle.MessageNode_Node_Property_To(), "",
msg_to)); //NON-NLS
sheetSet.put(new NodeProperty<>("Date", Bundle.MessageNode_Node_Property_Date(), "",
date)); //NON-NLS
return sheet;
}
@ -138,16 +141,16 @@ class MessageNode extends BlackboardArtifactNode {
public String getSourceName() {
return getDisplayName();
}
String getThreadID() {
return threadID;
}
@Override
public Action getPreferredAction() {
return preferredAction;
}
private int getAttachmentsCount() throws TskCoreException {
final BlackboardArtifact artifact = getArtifact();
int attachmentsCount;
@ -158,8 +161,7 @@ class MessageNode extends BlackboardArtifactNode {
try {
MessageAttachments msgAttachments = BlackboardJsonAttrUtil.fromAttribute(attachmentsAttr, MessageAttachments.class);
return msgAttachments.getAttachmentsCount();
}
catch (BlackboardJsonAttrUtil.InvalidJsonException ex) {
} catch (BlackboardJsonAttrUtil.InvalidJsonException ex) {
logger.log(Level.WARNING, String.format("Unable to parse json for MessageAttachments object in artifact: %s", artifact.getName()), ex);
return 0;
}

View File

@ -288,7 +288,7 @@ public class ContactArtifactViewer extends javax.swing.JPanel implements Artifac
* section panel.
*
* @param sectionAttributesList List of attributes to display.
* @param sectionLabel Section name label.
* @param sectionHeader Section name label.
* @param contactPanelLayout Panel layout.
* @param contactPanelConstraints Layout constraints.
*
@ -326,11 +326,9 @@ public class ContactArtifactViewer extends javax.swing.JPanel implements Artifac
}
/**
* Kicks off a search for personas, based in the given list of attributes.
* Initiates a search for Personas for the accounts associated with the
* Contact.
*
* @param accountAttributesList a list of account identifying attributes.
*
* @throws CentralRepoException
*/
@NbBundle.Messages({
"ContactArtifactViewer_persona_header=Persona",
@ -338,12 +336,6 @@ public class ContactArtifactViewer extends javax.swing.JPanel implements Artifac
"ContactArtifactViewer_cr_disabled_message=Enable Central Repository to view, create and edit personas.",
"ContactArtifactViewer_persona_unknown=Unknown"
})
/**
* Initiates a search for Personas for the accounts associated with the
* Contact.
*
*/
private void initiatePersonasSearch() {
// add a section header
@ -425,6 +417,7 @@ public class ContactArtifactViewer extends javax.swing.JPanel implements Artifac
* Displays the given persona in the persona panel.
*
* @param persona Persona to display.
* @param matchNumber Number of matches.
* @param missingAccountsList List of contact accounts this persona may be
* missing.
* @param gridBagLayout Layout to use.

View File

@ -33,6 +33,8 @@ import java.util.logging.Handler;
import java.util.logging.Level;
import javafx.application.Platform;
import javafx.embed.swing.JFXPanel;
import net.sf.sevenzipjbinding.SevenZip;
import net.sf.sevenzipjbinding.SevenZipNativeInitializationException;
import org.apache.commons.io.FileUtils;
import org.apache.commons.lang3.StringUtils;
import org.openide.modules.InstalledFileLocator;
@ -336,8 +338,8 @@ public class Installer extends ModuleInstall {
}
/**
* Make a folder in the config directory for object detection classifiers if one does not
* exist.
* Make a folder in the config directory for object detection classifiers if
* one does not exist.
*/
private static void ensureClassifierFolderExists() {
File objectDetectionClassifierDir = new File(PlatformUtil.getObjectDetectionClassifierPath());
@ -381,6 +383,7 @@ public class Installer extends ModuleInstall {
ensureClassifierFolderExists();
ensureOcrLanguagePacksFolderExists();
initJavaFx();
initializeSevenZip();
for (ModuleInstall mi : packageInstallers) {
try {
mi.restored();
@ -393,8 +396,21 @@ public class Installer extends ModuleInstall {
logger.log(Level.INFO, "Autopsy Core restore completed"); //NON-NLS
preloadJython();
}
/**
* Initializes 7zip-java bindings. We are performing initialization once
* because we encountered issues related to file locking when initialization
* was performed closer to where the bindings are used. See JIRA-6528.
*/
private void initializeSevenZip() {
try {
SevenZip.initSevenZipFromPlatformJAR();
logger.log(Level.INFO, "7zip-java bindings loaded"); //NON-NLS
} catch (SevenZipNativeInitializationException e) {
logger.log(Level.SEVERE, "Error loading 7zip-java bindings", e); //NON-NLS
}
}
/**
* Runs an initial load of the Jython modules to speed up subsequent loads.
*/
@ -403,13 +419,12 @@ public class Installer extends ModuleInstall {
try {
JythonModuleLoader.getIngestModuleFactories();
JythonModuleLoader.getGeneralReportModules();
}
catch (Exception ex) {
} catch (Exception ex) {
// This is a firewall exception to ensure that any possible exception caused
// by this initial load of the Jython modules are caught and logged.
logger.log(Level.SEVERE, "There was an error while doing an initial load of python plugins.", ex);
}
};
new Thread(loader).start();
}

View File

@ -450,6 +450,7 @@
<file name="cvt.wsmode" url="cvtWsmode.xml"/>
<file name="discovery.wsmode" url="discoveryWsmode.xml"/>
<file name="geolocation.wsmode" url="geolocationWsmode.xml"/>
<file name="personas.wsmode" url="personasWsmode.xml"/>
</folder>
</folder>

View File

@ -0,0 +1,11 @@
<?xml version="1.0" encoding="UTF-8"?>
<mode version="2.4">
<name unique="personas"/>
<kind type="editor"/>
<state type="separated"/>
<bounds x="76" y="68" width="1200" height="800"/>
<frame state="0"/>
<empty-behavior permanent="false"/>
</mode>

View File

@ -83,13 +83,19 @@ public final class FileTypesByMimeType extends Observable implements AutopsyVisi
private static final Set<Case.Events> CASE_EVENTS_OF_INTEREST = EnumSet.of(Case.Events.DATA_SOURCE_ADDED, Case.Events.CURRENT_CASE);
/**
* RefreshThrottler is used to limit the number of refreshes performed when
* CONTENT_CHANGED and DATA_ADDED ingest module events are received.
*/
private final RefreshThrottler refreshThrottler;
/**
* Create the base expression used as the where clause in the queries for
* files by mime type. Filters out certain kinds of files and directories,
* and known/slack files based on user preferences.
*
* @return The base expression to be used in the where clause of queries for
* files by mime type.
* files by mime type.
*/
private String createBaseWhereExpr() {
return "(dir_type = " + TskData.TSK_FS_NAME_TYPE_ENUM.REG.getValue() + ")"
@ -108,6 +114,7 @@ public final class FileTypesByMimeType extends Observable implements AutopsyVisi
private void removeListeners() {
deleteObservers();
IngestManager.getInstance().removeIngestJobEventListener(pcl);
refreshThrottler.unregisterEventListener();
Case.removeEventTypeSubscriber(CASE_EVENTS_OF_INTEREST, pcl);
}
@ -155,32 +162,20 @@ public final class FileTypesByMimeType extends Observable implements AutopsyVisi
this.typesRoot = typesRoot;
this.pcl = (PropertyChangeEvent evt) -> {
String eventType = evt.getPropertyName();
if (eventType.equals(IngestManager.IngestModuleEvent.CONTENT_CHANGED.toString())
|| eventType.equals(IngestManager.IngestJobEvent.COMPLETED.toString())
if (eventType.equals(IngestManager.IngestJobEvent.COMPLETED.toString())
|| eventType.equals(IngestManager.IngestJobEvent.CANCELLED.toString())
|| eventType.equals(Case.Events.DATA_SOURCE_ADDED.toString())) {
/**
* Checking for a current case is a stop gap measure until a
* different way of handling the closing of cases is worked out.
* Currently, remote events may be received for a case that is
* already closed.
*/
try {
Case.getCurrentCaseThrows();
typesRoot.updateShowCounts();
populateHashMap();
} catch (NoCurrentCaseException notUsed) {
/**
* Case is closed, do nothing.
*/
}
refreshMimeTypes();
} else if (eventType.equals(Case.Events.CURRENT_CASE.toString())) {
if (evt.getNewValue() == null) {
removeListeners();
}
}
};
refreshThrottler = new RefreshThrottler(new FileTypesByMimeTypeRefresher());
IngestManager.getInstance().addIngestJobEventListener(INGEST_JOB_EVENTS_OF_INTEREST, pcl);
refreshThrottler.registerForIngestModuleEvents();
Case.addEventTypeSubscriber(CASE_EVENTS_OF_INTEREST, pcl);
populateHashMap();
}
@ -201,7 +196,7 @@ public final class FileTypesByMimeType extends Observable implements AutopsyVisi
* @param node the Node which you wish to check.
*
* @return True if originNode is an instance of ByMimeTypeNode and is empty,
* false otherwise.
* false otherwise.
*/
public static boolean isEmptyMimeTypeNode(Node node) {
boolean isEmptyMimeNode = false;
@ -212,6 +207,41 @@ public final class FileTypesByMimeType extends Observable implements AutopsyVisi
}
private void refreshMimeTypes() {
/**
* Checking for a current case is a stop gap measure until a different
* way of handling the closing of cases is worked out. Currently, remote
* events may be received for a case that is already closed.
*/
try {
Case.getCurrentCaseThrows();
typesRoot.updateShowCounts();
populateHashMap();
} catch (NoCurrentCaseException notUsed) {
/**
* Case is closed, do nothing.
*/
}
}
/**
* Responsible for updating the 'By Mime Type' view in the UI. See
* RefreshThrottler for more details.
*/
private class FileTypesByMimeTypeRefresher implements RefreshThrottler.Refresher {
@Override
public void refresh() {
refreshMimeTypes();
}
@Override
public boolean isRefreshRequired(PropertyChangeEvent evt) {
return true;
}
}
/**
* Class which represents the root node of the "By MIME Type" tree, will
* have children of each media type present in the database or no children

View File

@ -78,7 +78,7 @@ final class MapWaypoint extends KdTree.XYZPoint implements org.jxmapviewer.viewe
artifactTypesToColors.put(BlackboardArtifact.ARTIFACT_TYPE.TSK_GPS_SEARCH.getTypeID(), Color.GREEN);
artifactTypesToColors.put(BlackboardArtifact.ARTIFACT_TYPE.TSK_GPS_TRACK.getTypeID(), Color.ORANGE);
artifactTypesToColors.put(BlackboardArtifact.ARTIFACT_TYPE.TSK_GPS_TRACKPOINT.getTypeID(), Color.ORANGE);
artifactTypesToColors.put(BlackboardArtifact.ARTIFACT_TYPE.TSK_METADATA_EXIF.getTypeID(), Color.CYAN);
artifactTypesToColors.put(BlackboardArtifact.ARTIFACT_TYPE.TSK_METADATA_EXIF.getTypeID(), Color.MAGENTA);
}
private final Waypoint dataModelWaypoint;

View File

@ -139,9 +139,10 @@ class SevenZipExtractor {
}
SevenZipExtractor(IngestJobContext context, FileTypeDetector fileTypeDetector, String moduleDirRelative, String moduleDirAbsolute) throws SevenZipNativeInitializationException {
if (!SevenZip.isInitializedSuccessfully() && (SevenZip.getLastInitializationException() == null)) {
SevenZip.initSevenZipFromPlatformJAR();
if (!SevenZip.isInitializedSuccessfully()) {
throw new SevenZipNativeInitializationException("SevenZip has not been previously initialized.");
}
this.context = context;
this.fileTypeDetector = fileTypeDetector;
this.moduleDirRelative = moduleDirRelative;

View File

@ -6,6 +6,7 @@ FilesIdentifierIngestModule.indexError.message=Failed to index interesting file
FilesSet.rule.dateRule.toString=(modified within {0} day(s))
FilesSetDefsPanel.bytes=Bytes
FilesSetDefsPanel.cancelImportMsg=Cancel import
FilesSetDefsPanel.cancelNewSetMsg=Cancel
# {0} - file name
FilesSetDefsPanel.exportButtonActionPerformed.fileExistPrompt=File {0} exists, overwrite?
FilesSetDefsPanel.gigaBytes=Gigabytes
@ -23,10 +24,12 @@ FilesSetDefsPanel.interesting.fileExtensionFilterLbl=Autopsy Interesting File Se
FilesSetDefsPanel.interesting.importButtonAction.featureName=Interesting Files Set Import
FilesSetDefsPanel.interesting.importOwConflict=Import Interesting files set conflict
FilesSetDefsPanel.interesting.importSetButton.text=Import Set
FilesSetDefsPanel.interesting.newOwConflict=Interesting files set conflict
# {0} - FilesSet name
FilesSetDefsPanel.interesting.overwriteSetPrompt=Interesting files set <{0}> already exists locally, overwrite?
FilesSetDefsPanel.interesting.overwriteSetPrompt=Interesting files set "{0}" already exists locally, overwrite?
# {0} - FilesSet name
FilesSetDefsPanel.interesting.standardFileConflict=A standard interesting file set already exists with the name <{0}>. Would you like to create a custom version of this file set?
# {1} - New FilesSet name
FilesSetDefsPanel.interesting.standardFileConflict=A standard interesting file set already exists with the name "{0}." Would you like to rename the set to "{1}?"
FilesSetDefsPanel.Interesting.Title=Global Interesting Items Settings
FilesSetDefsPanel.kiloBytes=Kilobytes
FilesSetDefsPanel.loadError=Error loading interesting files sets from file.
@ -144,4 +147,4 @@ FilesSetDefsPanel.pathLabel.text=Path Substring:
FilesSetDefsPanel.mimeTypeLabel.text=MIME Type:
FilesSetDefsPanel.fileSizeLabel.text=File Size:
# {0} - filesSetName
StandardInterestingFileSetsLoader.customSuffixed={0} (Custom)
StandardInterestingFileSetsLoader.customSuffixed={0} (Custom)

View File

@ -41,6 +41,7 @@ import javax.swing.filechooser.FileNameExtensionFilter;
import org.apache.commons.lang3.tuple.Pair;
import org.netbeans.spi.options.OptionsPanelController;
import org.openide.util.NbBundle;
import org.openide.util.NbBundle.Messages;
import org.openide.windows.WindowManager;
import org.sleuthkit.autopsy.corecomponents.OptionsPanel;
import org.sleuthkit.autopsy.coreutils.Logger;
@ -424,15 +425,6 @@ public final class FilesSetDefsPanel extends IngestModuleGlobalSettingsPanel imp
option = JOptionPane.showConfirmDialog(this, panel, NbBundle.getMessage(FilesSetPanel.class, filterDialogTitle), JOptionPane.OK_CANCEL_OPTION, JOptionPane.PLAIN_MESSAGE);
} while (option == JOptionPane.OK_OPTION && !panel.isValidDefinition());
// While adding new ruleset(selectedSet == null), if rule set with same name already exists, do not add to the filesSets hashMap.
// In case of editing an existing ruleset(selectedSet != null), following check is not performed.
if (this.filesSets.containsKey(panel.getFilesSetName()) && shouldCreateNew) {
MessageNotifyUtil.Message.error(NbBundle.getMessage(this.getClass(),
"FilesSetDefsPanel.doFileSetsDialog.duplicateRuleSet.text",
panel.getFilesSetName()));
return;
}
if (option == JOptionPane.OK_OPTION) {
Map<String, FilesSet.Rule> rules = new HashMap<>();
if (selectedSet != null) {
@ -450,10 +442,16 @@ public final class FilesSetDefsPanel extends IngestModuleGlobalSettingsPanel imp
rules
);
if (shouldCreateNew) {
this.replaceFilesSet(null, filesSet, null);
} else {
this.replaceFilesSet(selectedSet, filesSet, null);
Pair<FilesSet, Integer> result = handleConflict(filesSet, false);
option = result.getRight();
FilesSet toAddOrUpdate = result.getLeft();
if (result.getRight() == JOptionPane.OK_OPTION) {
if (shouldCreateNew) {
this.replaceFilesSet(null, toAddOrUpdate, null);
} else {
this.replaceFilesSet(selectedSet, toAddOrUpdate, null);
}
}
}
}
@ -519,10 +517,7 @@ public final class FilesSetDefsPanel extends IngestModuleGlobalSettingsPanel imp
*
* @param oldSet A set to replace, null if the new set is not a
* replacement.
* @param name The name of the files set.
* @param description The description of the files set.
* @param ignoresKnownFiles Whether or not the files set ignores known
* files.
* @param newSet The new set of rules.
* @param rules The set membership rules for the set. If null,
* the rules in the new set will be used.
*/
@ -534,7 +529,7 @@ public final class FilesSetDefsPanel extends IngestModuleGlobalSettingsPanel imp
}
FilesSet setToAdd = newSet;
// Make the new/edited set definition and add it to the working copy of
// the files set definitions.
if (rules != null) {
@ -1120,16 +1115,8 @@ public final class FilesSetDefsPanel extends IngestModuleGlobalSettingsPanel imp
this.doFileSetsDialog(this.setsList.getSelectedValue(), true);
firePropertyChange(OptionsPanelController.PROP_CHANGED, null, null);
}//GEN-LAST:event_copySetButtonActionPerformed
@NbBundle.Messages({
"FilesSetDefsPanel.yesOwMsg=Yes, overwrite",
"FilesSetDefsPanel.yesStandardFileConflictCreate=Yes, create",
"FilesSetDefsPanel.noSkipMsg=No, skip",
"FilesSetDefsPanel.cancelImportMsg=Cancel import",
"# {0} - FilesSet name",
"FilesSetDefsPanel.interesting.overwriteSetPrompt=Interesting files set <{0}> already exists locally, overwrite?",
"# {0} - FilesSet name",
"FilesSetDefsPanel.interesting.standardFileConflict=A standard interesting file set already exists with the name <{0}>. Would you like to create a custom version of this file set?",
"FilesSetDefsPanel.interesting.importOwConflict=Import Interesting files set conflict",
"FilesSetDefsPanel.interesting.failImportMsg=Interesting files set not imported",
"FilesSetDefsPanel.interesting.fileExtensionFilterLbl=Autopsy Interesting File Set File (xml)",
"FilesSetDefsPanel.interesting.importButtonAction.featureName=Interesting Files Set Import"
@ -1204,7 +1191,7 @@ public final class FilesSetDefsPanel extends IngestModuleGlobalSettingsPanel imp
FilesSet selectedSet = null;
for (FilesSet set : importedSets) {
Pair<FilesSet, Integer> conflictResult = handleConflict(set);
Pair<FilesSet, Integer> conflictResult = handleConflict(set, true);
int choice = conflictResult.getRight();
FilesSet resultingFilesSet = conflictResult.getLeft();
@ -1222,65 +1209,195 @@ public final class FilesSetDefsPanel extends IngestModuleGlobalSettingsPanel imp
/**
* Handles any possible conflicts that may arise from importing a files set.
*
* @param set The set to potentially import.
* @param set The set to potentially import.
* @param isImport The set with which to handle the conflict is being
* imported, otherwise this is a set to be added from the
* "New Set" button.
*
* @return A pair of the files set to be imported (or null if none) and the
* integer corresponding to the JOptionPane choice of the
* yes_no_cancel_option.
* JOptionPane.YES_NO_CANCEL option.
*/
private Pair<FilesSet, Integer> handleConflict(FilesSet set) {
private Pair<FilesSet, Integer> handleConflict(FilesSet set, boolean isImport) {
FilesSet conflict = this.filesSets.get(set.getName());
// if no conflict, return the files set as is with the option to proceed
if (conflict == null) {
return Pair.of(set, JOptionPane.OK_OPTION);
} else if (conflict.isStandardSet()) {
// if there is a conflict and the conflicting files set is a standard files set,
// see if allowing a custom files set is okay.
Object[] options = {
Bundle.FilesSetDefsPanel_yesStandardFileConflictCreate(),
Bundle.FilesSetDefsPanel_noSkipMsg(),
Bundle.FilesSetDefsPanel_cancelImportMsg()
};
int conflictChoice = JOptionPane.showOptionDialog(this,
Bundle.FilesSetDefsPanel_interesting_standardFileConflict(set.getName()),
Bundle.FilesSetDefsPanel_interesting_importOwConflict(),
JOptionPane.YES_NO_CANCEL_OPTION,
JOptionPane.QUESTION_MESSAGE,
null,
options,
options[0]);
// if it is okay, try again to see if there is a conflict.
if (conflictChoice == JOptionPane.OK_OPTION) {
return handleConflict(StandardInterestingFilesSetsLoader.getAsCustomFileSet(set));
}
return Pair.of(null, conflictChoice);
} else {
// if there is a conflict, see if it is okay to overwrite.
Object[] options = {
Bundle.FilesSetDefsPanel_yesOwMsg(),
Bundle.FilesSetDefsPanel_noSkipMsg(),
Bundle.FilesSetDefsPanel_cancelImportMsg()
};
int conflictChoice = JOptionPane.showOptionDialog(this,
Bundle.FilesSetDefsPanel_interesting_overwriteSetPrompt(set.getName()),
Bundle.FilesSetDefsPanel_interesting_importOwConflict(),
JOptionPane.YES_NO_CANCEL_OPTION,
JOptionPane.QUESTION_MESSAGE,
null,
options,
options[0]);
if (conflictChoice == JOptionPane.OK_OPTION) {
// if so, just return the files set to be placed in the map overwriting what is currently present.
return Pair.of(set, conflictChoice);
}
return Pair.of(null, conflictChoice);
}
if (isImport) {
if (conflict.isStandardSet()) {
return onImportStandardSetConflict(set);
} else {
return onImportConflict(set);
}
} else {
if (conflict.isStandardSet()) {
return onNewEditSetStandardSetConflict(set);
} else {
return onNewEditSetConflict(set);
}
}
}
/**
* When a user imports a files set and the files set name collides with a
* pre-existing files set (not a standard files set), the user is prompted
* for how they would like that handled (overwrite, skip, or cancel whole
* operation)
*
* @param set The set to be imported.
*
* @return a pair of the files set and the JOptionPane.YES_NO_CANCEL option
*/
@Messages({
"FilesSetDefsPanel.yesOwMsg=Yes, overwrite",
"FilesSetDefsPanel.noSkipMsg=No, skip",
"FilesSetDefsPanel.cancelImportMsg=Cancel import",
"# {0} - FilesSet name",
"FilesSetDefsPanel.interesting.overwriteSetPrompt=Interesting files set \"{0}\" already exists locally, overwrite?",
"FilesSetDefsPanel.interesting.importOwConflict=Import Interesting files set conflict",})
private Pair<FilesSet, Integer> onImportConflict(FilesSet set) {
// if there is a conflict, see if it is okay to overwrite.
Object[] options = {
Bundle.FilesSetDefsPanel_yesOwMsg(),
Bundle.FilesSetDefsPanel_noSkipMsg(),
Bundle.FilesSetDefsPanel_cancelImportMsg()
};
int conflictChoice = JOptionPane.showOptionDialog(this,
Bundle.FilesSetDefsPanel_interesting_overwriteSetPrompt(set.getName()),
Bundle.FilesSetDefsPanel_interesting_importOwConflict(),
JOptionPane.YES_NO_CANCEL_OPTION,
JOptionPane.QUESTION_MESSAGE,
null,
options,
options[0]);
if (conflictChoice == JOptionPane.OK_OPTION) {
// if so, just return the files set to be placed in the map overwriting what is currently present.
return Pair.of(set, conflictChoice);
}
return Pair.of(null, conflictChoice);
}
/**
* When a user imports a files set and the files set name collides with a
* pre-existing standard files set, the user is prompted for how they would
* like that handled (create files set with a " custom" suffix, skip, or
* cancel whole operation)
*
* @param set The set to be imported.
*
* @return a pair of the files set and the JOptionPane.YES_NO_CANCEL option
*/
@Messages({
"FilesSetDefsPanel.yesStandardFileConflictCreate=Yes, create",
"# {0} - FilesSet name",
"# {1} - New FilesSet name",
"FilesSetDefsPanel.interesting.standardFileConflict=A standard interesting file set already exists with the name \"{0}.\" Would you like to rename your set to \"{1}?\"",})
private Pair<FilesSet, Integer> onImportStandardSetConflict(FilesSet set) {
// if there is a conflict and the conflicting files set is a standard files set,
// see if allowing a custom files set is okay.
Object[] options = {
Bundle.FilesSetDefsPanel_yesStandardFileConflictCreate(),
Bundle.FilesSetDefsPanel_noSkipMsg(),
Bundle.FilesSetDefsPanel_cancelImportMsg()
};
String setName = set.getName();
String customSetName = Bundle.StandardInterestingFileSetsLoader_customSuffixed(set.getName());
int conflictChoice = JOptionPane.showOptionDialog(this,
Bundle.FilesSetDefsPanel_interesting_standardFileConflict(setName, customSetName),
Bundle.FilesSetDefsPanel_interesting_importOwConflict(),
JOptionPane.YES_NO_CANCEL_OPTION,
JOptionPane.QUESTION_MESSAGE,
null,
options,
options[0]);
// if it is okay to create with custom prefix, try again to see if there is a conflict.
if (conflictChoice == JOptionPane.OK_OPTION) {
return handleConflict(StandardInterestingFilesSetsLoader.getAsCustomFileSet(set), true);
}
return Pair.of(null, conflictChoice);
}
/**
* When a user creates a files set or edits a files set and the files set
* name collides with a pre-existing files set (not a standard files set),
* the user is prompted for how they would like that handled (overwrite or
* cancel whole operation)
*
* @param set The set to be added.
*
* @return a pair of the files set and the JOptionPane.YES_NO_CANCEL option
*/
@Messages({
"FilesSetDefsPanel.cancelNewSetMsg=Cancel",
"FilesSetDefsPanel.interesting.newOwConflict=Interesting files set conflict",})
private Pair<FilesSet, Integer> onNewEditSetConflict(FilesSet set) {
// if there is a conflict, see if it is okay to overwrite.
Object[] options = {
Bundle.FilesSetDefsPanel_yesOwMsg(),
Bundle.FilesSetDefsPanel_cancelNewSetMsg()
};
int conflictChoice = JOptionPane.showOptionDialog(this,
Bundle.FilesSetDefsPanel_interesting_overwriteSetPrompt(set.getName()),
Bundle.FilesSetDefsPanel_interesting_newOwConflict(),
JOptionPane.OK_CANCEL_OPTION,
JOptionPane.QUESTION_MESSAGE,
null,
options,
options[0]);
if (conflictChoice == JOptionPane.OK_OPTION) {
// if so, just return the files set to be placed in the map overwriting what is currently present.
return Pair.of(set, conflictChoice);
}
return Pair.of(null, conflictChoice);
}
/**
* When a user creates a files set and the files set name collides with a
* pre-existing standard files set, the user is prompted for how they would
* like that handled (create files set with a " custom" suffix or cancel
* whole operation)
*
* @param set The set to be adedd.
*
* @return a pair of the files set and the JOptionPane.YES_NO_CANCEL option
*/
private Pair<FilesSet, Integer> onNewEditSetStandardSetConflict(FilesSet set) {
// if there is a conflict and the conflicting files set is a standard files set,
// see if allowing a custom files set is okay.
Object[] options = {
Bundle.FilesSetDefsPanel_yesStandardFileConflictCreate(),
Bundle.FilesSetDefsPanel_cancelNewSetMsg()
};
String setName = set.getName();
String customSetName = Bundle.StandardInterestingFileSetsLoader_customSuffixed(set.getName());
int conflictChoice = JOptionPane.showOptionDialog(this,
Bundle.FilesSetDefsPanel_interesting_standardFileConflict(setName, customSetName),
Bundle.FilesSetDefsPanel_interesting_newOwConflict(),
JOptionPane.OK_CANCEL_OPTION,
JOptionPane.QUESTION_MESSAGE,
null,
options,
options[0]);
// if it is okay to create with custom prefix, try again to see if there is a conflict.
if (conflictChoice == JOptionPane.OK_OPTION) {
return handleConflict(StandardInterestingFilesSetsLoader.getAsCustomFileSet(set), false);
}
return Pair.of(null, conflictChoice);
}
@NbBundle.Messages({"FilesSetDefsPanel.interesting.exportButtonAction.featureName=Interesting Files Set Export",

View File

@ -26,6 +26,7 @@ import java.io.Serializable;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@ -51,6 +52,9 @@ import org.sleuthkit.autopsy.modules.interestingitems.FilesSetsManager.FilesSets
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NodeList;
import java.util.Comparator;
import java.util.function.Function;
import java.util.stream.Collectors;
class InterestingItemsFilesSetSettings implements Serializable {
@ -536,6 +540,34 @@ class InterestingItemsFilesSetSettings implements Serializable {
}
return true;
}
/**
* Generates an alphabetically sorted list based on the provided collection and Function to retrieve a string field from each object.
* @param itemsToSort The items to be sorted into the newly generated list.
* @param getName The method to retrieve the given field from the object.
* @return The newly generated list sorted alphabetically by the given field.
*/
private static <T> List<T> sortOnField(Collection<T> itemsToSort, final Function<T, String> getName) {
Comparator<T> comparator = (a,b) -> {
String aName = getName.apply(a);
String bName = getName.apply(b);
if (aName == null) {
aName = "";
}
if (bName == null) {
bName = "";
}
return aName.compareToIgnoreCase(bName);
};
return itemsToSort.stream()
.sorted(comparator)
.collect(Collectors.toList());
}
/**
* Write the FilesSets to a file as an xml.
@ -555,7 +587,12 @@ class InterestingItemsFilesSetSettings implements Serializable {
Element rootElement = doc.createElement(FILE_SETS_ROOT_TAG);
doc.appendChild(rootElement);
// Add the interesting files sets to the document.
for (FilesSet set : interestingFilesSets) {
List<FilesSet> sortedFilesSets = sortOnField(
interestingFilesSets,
filesSet -> filesSet == null ? null : filesSet.getName());
for (FilesSet set : sortedFilesSets) {
// Add the files set element and its attributes.
Element setElement = doc.createElement(FILE_SET_TAG);
setElement.setAttribute(NAME_ATTR, set.getName());
@ -565,7 +602,12 @@ class InterestingItemsFilesSetSettings implements Serializable {
setElement.setAttribute(VERSION_NUMBER, Integer.toString(set.getVersionNumber()));
// Add the child elements for the set membership rules.
// All conditions of a rule will be written as a single element in the xml
for (FilesSet.Rule rule : set.getRules().values()) {
List<FilesSet.Rule> sortedRules = sortOnField(
set.getRules().values(),
rule -> rule == null ? null : rule.getName());
for (FilesSet.Rule rule : sortedRules) {
// Add a rule element with the appropriate name Condition
// type tag.
Element ruleElement;

View File

@ -151,6 +151,7 @@ final class ReportVisualPanel1 extends JPanel implements ListSelectionListener {
}
modulesJList.getSelectionModel().addListSelectionListener(this);
modulesJList.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
modulesJList.setCellRenderer(new ModuleCellRenderer());
modulesJList.setListData(modules.toArray(new ReportModule[modules.size()]));
modulesJList.setSelectedIndex(selectedIndex);

View File

@ -19,6 +19,9 @@
package org.sleuthkit.autopsy.tags;
import java.util.logging.Level;
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.TagName;
import org.sleuthkit.datamodel.TagSet;
@ -52,12 +55,13 @@ public final class TagUtils {
public static String getDecoratedTagDisplayName(TagName tagName) {
String displayName = tagName.getDisplayName();
try {
TagSet tagSet = tagName.getTagSet();
TagsManager tagsManager = Case.getCurrentCaseThrows().getServices().getTagsManager();
TagSet tagSet = tagsManager.getTagSet(tagName);
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()));
} catch (NoCurrentCaseException | TskCoreException ex) {
logger.log(Level.SEVERE, String.format("Failed to get TagSet for TagName '%s' (ID=%d)", tagName.getDisplayName(), tagName.getId()));
}
if (tagName.getKnownStatus() == TskData.FileKnown.BAD) {

View File

@ -62,7 +62,7 @@ public final class TextFileExtractor implements TextExtractor {
encoding = StandardCharsets.UTF_8;
}
} catch (TskCoreException | IOException ex) {
logger.log(Level.SEVERE, String.format("Error detecting the "
logger.log(Level.WARNING, String.format("Error detecting the "
+ "encoding for %s (objID=%d)", file.getName(), file.getId()), ex);
encoding = StandardCharsets.UTF_8;
}

View File

@ -135,7 +135,7 @@
<compile-dependency/>
<run-dependency>
<release-version>10</release-version>
<specification-version>10.19</specification-version>
<specification-version>10.20</specification-version>
</run-dependency>
</dependency>
<dependency>

View File

@ -1,7 +1,7 @@
/*
* Autopsy Forensic Browser
*
* Copyright 2015 Basis Technology Corp.
* Copyright 2015-2020 Basis Technology Corp.
* Contact: carrier <at> sleuthkit <dot> org
*
* Licensed under the Apache License, Version 2.0 (the "License");
@ -71,16 +71,26 @@ public final class AutopsyManifestFileParser implements ManifestFileParser {
Date dateFileCreated = new Date(attrs.creationTime().toMillis());
Document doc = this.createManifestDOM(filePath);
XPath xpath = XPathFactory.newInstance().newXPath();
XPathExpression expr = xpath.compile(CASE_NAME_XPATH);
String caseName = (String) expr.evaluate(doc, XPathConstants.STRING);
if (caseName.isEmpty()) {
throw new ManifestFileParserException("Case name not found, manifest is invalid");
}
expr = xpath.compile(DEVICE_ID_XPATH);
String deviceId = (String) expr.evaluate(doc, XPathConstants.STRING);
if (deviceId.isEmpty()) {
deviceId = UUID.randomUUID().toString();
}
expr = xpath.compile(DATA_SOURCE_NAME_XPATH);
String dataSourceName = (String) expr.evaluate(doc, XPathConstants.STRING);
if (dataSourceName.isEmpty()) {
throw new ManifestFileParserException("Data source path not found, manifest is invalid");
}
Path dataSourcePath = filePath.getParent().resolve(dataSourceName);
return new Manifest(filePath, dateFileCreated, caseName, deviceId, dataSourcePath, new HashMap<>());
} catch (Exception ex) {
throw new ManifestFileParserException(String.format("Error parsing manifest %s", filePath), ex);

View File

@ -127,7 +127,7 @@
<compile-dependency/>
<run-dependency>
<release-version>10</release-version>
<specification-version>10.19</specification-version>
<specification-version>10.20</specification-version>
</run-dependency>
</dependency>
<dependency>

View File

@ -42,6 +42,7 @@ from org.sleuthkit.datamodel import TskCoreException
import traceback
import general
import struct
import os
"""
Parses cache files that Android maintains for Wifi and cell towers. Adds GPS points to blackboard.
@ -79,35 +80,39 @@ class CacheLocationAnalyzer(general.AndroidComponentAnalyzer):
# code to parse the cache.wifi and cache.cell taken from https://forensics.spreitzenbarth.de/2011/10/28/decoding-cache-cell-and-cache-wifi-files/
cacheFile = open(str(file), 'rb')
(version, entries) = struct.unpack('>hh', cacheFile.read(4))
i = 0
while i < entries:
key = cacheFile.read(struct.unpack('>h', cacheFile.read(2))[0])
(accuracy, confidence, latitude, longitude, readtime) = struct.unpack('>iiddQ', cacheFile.read(32))
timestamp = readtime/1000
i = i + 1
# Check the number of entries * 32 (entry record size) to see if it is bigger then the file, this is a indication the file is malformed or corrupted
if ((entries * 32) < abstractFile.getSize()):
i = 0
self._logger.log(Level.INFO, "Number of Entries is " + str(entries) + " File size is " + str(abstractFile.getSize()))
while i < entries:
key = cacheFile.read(struct.unpack('>h', cacheFile.read(2))[0])
(accuracy, confidence, latitude, longitude, readtime) = struct.unpack('>iiddQ', cacheFile.read(32))
timestamp = readtime/1000
i = i + 1
attributes = ArrayList()
artifact = abstractFile.newArtifact(BlackboardArtifact.ARTIFACT_TYPE.TSK_GPS_BOOKMARK)
attributes.add(BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_GEO_LATITUDE, general.MODULE_NAME, latitude))
attributes.add(BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_GEO_LONGITUDE, general.MODULE_NAME, longitude))
attributes.add(BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DATETIME, general.MODULE_NAME, timestamp))
attributes.add(BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_PROG_NAME, general.MODULE_NAME,
abstractFile.getName() + " Location History"))
artifact.addAttributes(attributes)
#Not storing these for now.
# artifact.addAttribute(BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_VALUE.getTypeID(), AndroidModuleFactorymodule.moduleName, accuracy))
# artifact.addAttribute(BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_COMMENT.getTypeID(), AndroidModuleFactorymodule.moduleName, confidence))
try:
# index the artifact for keyword search
blackboard = Case.getCurrentCase().getSleuthkitCase().getBlackboard()
blackboard.postArtifact(artifact, general.MODULE_NAME)
except Blackboard.BlackboardException as ex:
self._logger.log(Level.SEVERE, "Unable to index blackboard artifact " + str(artifact.getArtifactID()), ex)
self._logger.log(Level.SEVERE, traceback.format_exc())
MessageNotifyUtil.Notify.error("Failed to index GPS trackpoint artifact for keyword search.", artifact.getDisplayName())
cacheFile.close()
attributes = ArrayList()
artifact = abstractFile.newArtifact(BlackboardArtifact.ARTIFACT_TYPE.TSK_GPS_BOOKMARK)
attributes.add(BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_GEO_LATITUDE, general.MODULE_NAME, latitude))
attributes.add(BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_GEO_LONGITUDE, general.MODULE_NAME, longitude))
attributes.add(BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DATETIME, general.MODULE_NAME, timestamp))
attributes.add(BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_PROG_NAME, general.MODULE_NAME,
abstractFile.getName() + " Location History"))
artifact.addAttributes(attributes)
#Not storing these for now.
# artifact.addAttribute(BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_VALUE.getTypeID(), AndroidModuleFactorymodule.moduleName, accuracy))
# artifact.addAttribute(BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_COMMENT.getTypeID(), AndroidModuleFactorymodule.moduleName, confidence))
try:
# index the artifact for keyword search
blackboard = Case.getCurrentCase().getSleuthkitCase().getBlackboard()
blackboard.postArtifact(artifact, general.MODULE_NAME)
except Blackboard.BlackboardException as ex:
self._logger.log(Level.SEVERE, "Unable to index blackboard artifact " + str(artifact.getArtifactID()), ex)
self._logger.log(Level.SEVERE, traceback.format_exc())
MessageNotifyUtil.Notify.error("Failed to index GPS trackpoint artifact for keyword search.", artifact.getDisplayName())
cacheFile.close()
else:
self._logger.log(Level.WARNING, "Number of entries in file exceeds file size of file " + os.path.join(abstractFile.getParentPath(), abstractFile.getName()))
except Exception as ex:
self._logger.log(Level.SEVERE, "Error parsing Cached GPS locations to blackboard", ex)
self._logger.log(Level.SEVERE, traceback.format_exc())

View File

@ -119,7 +119,7 @@
<compile-dependency/>
<run-dependency>
<release-version>10</release-version>
<specification-version>10.19</specification-version>
<specification-version>10.20</specification-version>
</run-dependency>
</dependency>
<dependency>

View File

@ -60,7 +60,7 @@
<compile-dependency/>
<run-dependency>
<release-version>10</release-version>
<specification-version>10.19</specification-version>
<specification-version>10.20</specification-version>
</run-dependency>
</dependency>
<dependency>

View File

@ -47,7 +47,7 @@
<compile-dependency/>
<run-dependency>
<release-version>10</release-version>
<specification-version>10.19</specification-version>
<specification-version>10.20</specification-version>
</run-dependency>
</dependency>
<dependency>

View File

@ -1,5 +1,5 @@
#Updated by build script
#Fri, 19 Jun 2020 10:14:47 -0400
#Wed, 08 Jul 2020 15:15:46 -0400
LBL_splash_window_title=Starting Autopsy
SPLASH_HEIGHT=314
SPLASH_WIDTH=538
@ -8,4 +8,4 @@ SplashRunningTextBounds=0,289,538,18
SplashRunningTextColor=0x0
SplashRunningTextFontSize=19
currentVersion=Autopsy 4.15.0
currentVersion=Autopsy 4.16.0

View File

@ -1,4 +1,4 @@
#Updated by build script
#Fri, 19 Jun 2020 10:14:47 -0400
CTL_MainWindow_Title=Autopsy 4.15.0
CTL_MainWindow_Title_No_Project=Autopsy 4.15.0
#Wed, 08 Jul 2020 15:15:46 -0400
CTL_MainWindow_Title=Autopsy 4.16.0
CTL_MainWindow_Title_No_Project=Autopsy 4.16.0

View File

@ -38,7 +38,7 @@ PROJECT_NAME = "Autopsy User Documentation"
# could be handy for archiving the generated documentation or if some version
# control system is used.
PROJECT_NUMBER = 4.15.0
PROJECT_NUMBER = 4.16.0
# Using the PROJECT_BRIEF tag one can provide an optional one line description
# for a project that appears at the top of each page and should give viewer a
@ -1025,7 +1025,7 @@ GENERATE_HTML = YES
# The default directory is: html.
# This tag requires that the tag GENERATE_HTML is set to YES.
HTML_OUTPUT = 4.15.0
HTML_OUTPUT = 4.16.0
# The HTML_FILE_EXTENSION tag can be used to specify the file extension for each
# generated HTML page (for example: .htm, .php, .asp).

View File

@ -57,7 +57,7 @@ If you right-click on a case, you can open it, see the log, delete the case, or
Note that you can select multiple cases at once to delete. If you choose to delete a case (or cases), you'll see the following confirmation dialog:
\image html case_delete_confirm.png
\image html AutoIngest/case_delete_confirm.png
\section auto_ingest_admin_health_monitor Health Monitor

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 22 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 23 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 75 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 54 KiB

After

Width:  |  Height:  |  Size: 68 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 66 KiB

After

Width:  |  Height:  |  Size: 70 KiB

View File

@ -15,7 +15,7 @@ This module allows you to make sets of rules that will be run against each file
\section interesting_files_config Configuration
To create and edit your rule sets, go to "Tools", "Options" and then select the "Interesting Files" tab. The area on the left side will show you a list of all the rule sets that are currently available. Selecting a rule set will display its description and information about each of its rules on the right side of the panel.
To create and edit your rule sets, go to "Tools", "Options" and then select the "Interesting Files" tab. The area on the left side will show you a list of all the rule sets that are currently available. This will include the official rule sets that are included with Autopsy and any rule sets that you create. Selecting a rule set will display its description and information about each of its rules on the right side of the panel.
\image html InterestingFiles/main.png
@ -31,6 +31,8 @@ The buttons on the bottom of the left side of the panel control the rule sets.
<li><b>Export Set</b> - Exports the selected rule set in a format that can be shared with other Autopsy users.
</ul>
Note that the predefined rule sets can not be deleted or edited. If you believe you have additions that would be useful to the community, see the \ref update_interesting_files_page page for instructions on submitting updates.
Selecting a rule set will display its description, whether it ignores known files, and the rules contained in the set. Selecting a rule will display the conditions for that rule in the "Rule Details" section.
The buttons under the list of rules allow you to create new rules and edit or delete existing rules. Selecting "New Rule" will bring up a new window to create the rule.

View File

@ -93,7 +93,9 @@ The following topics are available here:
- \ref object_detection_page
- \ref volatility_dsp_page
- \subpage translations_page
- Community Contributions
- \subpage translations_page
- \subpage update_interesting_files_page
If the topic you need is not listed, then you can:

View File

@ -22,7 +22,7 @@ Ingest Settings
------
The run-time setting for this module allows you to choose whether to keep corrupted files.
\image html photo_rec_settings.png
\image html photo_rec_settings.PNG
Also note that the "Run ingest modules on" selection needs to include unallocated space for this module to run.

View File

@ -22,7 +22,7 @@ At this point there are three options:
- New tag -- Create a new tag and add it to the file/result
\image html tagging_new_tag.png
\image html tagging_new_tag.PNG
There are several default tag names:
- Bookmark - Default tag for marking files of interest

View File

@ -56,7 +56,7 @@ VHD is a file format used by Microsoft Virtual Machines that is readable by Wind
To create a sparse VHD, check the box for "Make a VHD image..." when selecting the disk to analyze.
\image html createVHD.png
\image html triage/createVHD.png
\section triage_scenarios Scenarios

View File

@ -5,12 +5,12 @@ The user interface quick search feature allows you to search within the data on
How to use it
-----
In order to use the search you need to select any item in the area you wish to search, and start typing. If user interface quick search is available in the area you have selected a search field will appear in the bottom left hand corner of the area. As you type the string you are searching for it will auto-update to select one of the results which matches your string. You can switch between the results which match the string you have typed with the up and down keys. The search does not support the use of regular expressions but will match against any sub-sting in the fields it searches, not just at the beginning of the field.
\image html quick_search_result.PNG
\image html quick_search_result.png
Configuration
-----
By default the search will match against the data in all fields which are in the currently selected area. The search will also ignore case by default. If you want to change either of these default behaviors you can click the magnifying glass with the down arrow icon and configure which columns will be searched as well as if the search should ignore case.
\image html quick_search_configuration.PNG
\image html quick_search_configuration.png
Where it can be used
-----

View File

@ -0,0 +1,26 @@
/*! \page update_interesting_files_page Updating the Official Interesting File Sets
The \ref interesting_files_identifier_page contains several official rule sets. You can select a rule set to display the rules it contains in the middle of the right side of the panel.
\image html InterestingFiles/if_official_rule_details.png
If you have one or more rules that you think should be included in an official rule set you can submit your new rules using the process below. Consult the \ref interesting_files_config section for general instructions on creating and editing interesting file sets.
<ol>
<li> Create a new interesting file set. Give it a name similar to the set you wish to update to make it clear which set your new rules belong to. Do not copy the existing rule set.
\image html InterestingFiles/if_create_set.png
<li> Create your rule(s). Make sure each rule has a "Rule Name" that identifies the application it is detecting. Click the "Apply" button on the main panel when done.
\image html InterestingFiles/if_new_rule.png
<li> Export the set as XML.
\image html InterestingFiles/if_export.png
<li> Create an Autopsy Github issue that identifes the set to update and what applications were added, and attach the XML. Go to: https://github.com/sleuthkit/autopsy/issues
</ol>
*/

View File

@ -14,7 +14,7 @@ If you have a disk image associated with your memory image, ingest the disk imag
On the next screen, you can select your memory image and then adjust the settings to choose a profile and which Volatility plugins to run.
\image html volatility_dsp_config.png
\image html volatility_dsp_config.PNG
Next you'll see the ingest module configuration panel. No ingest modules will be run when using the Volatility data source processor, so simply hit the "Next" button. When it finishes, you may have some non-critical errors. These frequently come from the data source processor being unable to find files in the original disk image. If you did not add the associated disk image before running the Volatility data source processor on the memory image, there will be a large number of these errors but the Volatility module output will still be available.

View File

@ -38,7 +38,7 @@ PROJECT_NAME = "Autopsy"
# could be handy for archiving the generated documentation or if some version
# control system is used.
PROJECT_NUMBER = 4.15.0
PROJECT_NUMBER = 4.16.0
# Using the PROJECT_BRIEF tag one can provide an optional one line description
# for a project that appears a the top of each page and should give viewer a
@ -1066,7 +1066,7 @@ GENERATE_HTML = YES
# The default directory is: html.
# This tag requires that the tag GENERATE_HTML is set to YES.
HTML_OUTPUT = api-docs/4.15.0/
HTML_OUTPUT = api-docs/4.16.0/
# The HTML_FILE_EXTENSION tag can be used to specify the file extension for each
# generated HTML page (for example: .htm, .php, .asp).

View File

@ -4,7 +4,7 @@ app.title=Autopsy
### lowercase version of above
app.name=${branding.token}
### if left unset, version will default to today's date
app.version=4.15.0
app.version=4.16.0
### build.type must be one of: DEVELOPMENT, RELEASE
#build.type=RELEASE
build.type=DEVELOPMENT

View File

@ -0,0 +1,220 @@
"""This script determines the updated, added, and deleted properties from the '.properties-MERGED' files
and generates a csv file containing the items changed. This script requires the python libraries:
gitpython and jproperties. As a consequence, it also requires git >= 1.7.0 and python >= 3.4.
"""
from git import Repo
from typing import List, Dict, Tuple
import re
import csv
from jproperties import Properties
import sys
class ItemChange:
def __init__(self, rel_path: str, key: str, prev_val: str, cur_val: str):
"""Describes the change that occurred for a particular key of a properties file.
Args:
rel_path (str): The relative path of the properties file.
key (str): The key in the properties file.
prev_val (str): The previous value for the key.
cur_val (str): The current value for the key.
"""
self.rel_path = rel_path
self.key = key
self.prev_val = prev_val
self.cur_val = cur_val
if ItemChange.has_str_content(cur_val) and not ItemChange.has_str_content(prev_val):
self.type = 'ADDITION'
elif not ItemChange.has_str_content(cur_val) and ItemChange.has_str_content(prev_val):
self.type = 'DELETION'
else:
self.type = 'CHANGE'
@staticmethod
def has_str_content(content: str):
"""Determines whether or not the content is empty or None.
Args:
content (str): The text.
Returns:
bool: Whether or not it has content.
"""
return content is not None and len(content.strip()) > 0
@staticmethod
def get_headers() -> List[str]:
"""Returns the csv headers to insert when serializing a list of ItemChange objects to csv.
Returns:
List[str]: The column headers
"""
return ['Relative Path', 'Key', 'Change Type', 'Previous Value', 'Current Value']
def get_row(self) -> List[str]:
"""Returns the list of values to be entered as a row in csv serialization.
Returns:
List[str]: The list of values to be entered as a row in csv serialization.
"""
return [
self.rel_path,
self.key,
self.type,
self.prev_val,
self.cur_val]
def get_entry_dict(diff_str: str) -> Dict[str, str]:
"""Retrieves a dictionary mapping the properties represented in the string.
Args:
diff_str (str): The string of the properties file.
Returns:
Dict[str,str]: The mapping of keys to values in that properties file.
"""
props = Properties()
props.load(diff_str, "utf-8")
return props.properties
def get_item_change(rel_path: str, key: str, prev_val: str, cur_val: str) -> ItemChange:
"""Returns an ItemChange object if the previous value is not equal to the current value.
Args:
rel_path (str): The relative path for the properties file.
key (str): The key within the properties file for this potential change.
prev_val (str): The previous value.
cur_val (str): The current value.
Returns:
ItemChange: The ItemChange object or None if values are the same.
"""
if (prev_val == cur_val):
return None
else:
return ItemChange(rel_path, key, prev_val, cur_val)
def get_changed(rel_path: str, a_str: str, b_str: str) -> List[ItemChange]:
"""Given the relative path of the properties file that
Args:
rel_path (str): The relative path for the properties file.
a_str (str): The string representing the original state of the file.
b_str (str): The string representing the current state of the file.
Returns:
List[ItemChange]: The changes determined.
"""
print('Retrieving changes for {}...'.format(rel_path))
a_dict = get_entry_dict(a_str)
b_dict = get_entry_dict(b_str)
all_keys = set().union(a_dict.keys(), b_dict.keys())
mapped = map(lambda key: get_item_change(
rel_path, key, a_dict.get(key), b_dict.get(key)), all_keys)
return filter(lambda entry: entry is not None, mapped)
def get_text(blob) -> str:
return blob.data_stream.read().decode('utf-8')
def get_changed_from_diff(rel_path: str, diff) -> List[ItemChange]:
"""Determines changes from a git python diff.
Args:
rel_path (str): The relative path for the properties file.
diff: The git python diff.
Returns:
List[ItemChange]: The changes in properties.
"""
# an item was added
if diff.change_type == 'A':
changes = get_changed(rel_path, '', get_text(diff.b_blob))
# an item was deleted
elif diff.change_type == 'D':
changes = get_changed(rel_path, get_text(diff.a_blob), '')
# an item was modified
elif diff.change_type == 'M':
changes = get_changed(rel_path, get_text(
diff.a_blob), get_text(diff.b_blob))
else:
changes = []
return changes
def get_rel_path(diff) -> str:
"""Determines the relative path based on the git python.
Args:
diff: The git python diff.
Returns:
str: The determined relative path.
"""
if diff.b_path is not None:
return diff.b_path
elif diff.a_path is not None:
return diff.a_path
else:
return '<Uknown Path>'
def write_diff_to_csv(repo_path: str, output_path: str, commit_1_id: str, commit_2_id: str):
"""Determines the changes made in '.properties-MERGED' files from one commit to another commit.
Args:
repo_path (str): The local path to the git repo.
output_path (str): The output path for the csv file.
commit_1_id (str): The initial commit for the diff.
commit_2_id (str): The latest commit for the diff.
"""
repo = Repo(repo_path)
commit_1 = repo.commit(commit_1_id)
commit_2 = repo.commit(commit_2_id)
diffs = commit_1.diff(commit_2)
with open(output_path, 'w', newline='') as csvfile:
writer = csv.writer(csvfile)
writer.writerow(ItemChange.get_headers())
for diff in diffs:
rel_path = get_rel_path(diff)
if not rel_path.endswith('.properties-MERGED'):
continue
changes = get_changed_from_diff(rel_path, diff)
for item_change in changes:
writer.writerow(item_change.get_row())
def print_help():
"""Prints a quick help message.
"""
print("diffscript.py [path to repo] [csv output path] [commit for previous release] [commit for current release (optional; defaults to 'HEAD')]")
def main():
if len(sys.argv) <= 3:
print_help()
sys.exit(1)
repo_path = sys.argv[1]
output_path = sys.argv[2]
commit_1_id = sys.argv[3]
commit_2_id = sys.argv[4] if len(sys.argv) > 4 else 'HEAD'
write_diff_to_csv(repo_path, output_path, commit_1_id, commit_2_id)
sys.exit(0)
if __name__ == "__main__":
main()

View File

@ -1,23 +1,25 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<INTERESTING_FILE_SETS>
<INTERESTING_FILE_SET description="Finds Encryption Programs installed on the machine" ignoreKnown="false" name="Encryption Programs" standardSet="true" versionNumber="1">
<NAME name="Cryptomator" regex="false" typeFilter="file">Cryptomator.exe</NAME>
<NAME name="Gpg4win" regex="false" typeFilter="file">gdbus.exe</NAME>
<NAME name="Gihosoft File Encryption" regex="false" typeFilter="file">GFileEncryption.exe</NAME>
<NAME name="EncFSMP" regex="false" typeFilter="file">EncFSMP.exe</NAME>
<NAME name="Tor Browser" regex="false" typeFilter="all">Tor Browser</NAME>
<NAME name="Proton Bridge" regex="false" typeFilter="file">Desktop-Bridge.exe</NAME>
<NAME name="CryptoExpert 8" regex="false" typeFilter="file">cexpertcmd.exe</NAME>
<NAME name="Encrypto" regex="false" typeFilter="file">Encrypto.exe</NAME>
<INTERESTING_FILE_SET description="Finds Encryption Programs installed on the machine" ignoreKnown="false" name="Encryption Programs" standardSet="true" versionNumber="2">
<NAME name="aescrypt" regex="false" typeFilter="file">aescrypt.exe</NAME>
<NAME name="certainsafe" regex="false" typeFilter="file">certainsafe.exe</NAME>
<NAME name="Folder Lock" regex="false" typeFilter="file">Folder Lock.exe</NAME>
<NAME name="BitLocker" regex="false" typeFilter="all">BitLockerDeviceEncryption.exe</NAME>
<NAME name="VeraCrypt" regex="false" typeFilter="file">VeraCrypt.exe</NAME>
<NAME name="CryptoExpert 8" regex="false" typeFilter="file"> cexpert_gui.exe</NAME>
<NAME name="GnuPG" regex="false" typeFilter="file"> gpg.exe</NAME>
<NAME name="AxCrypt" regex="false" typeFilter="file">AxCrypt.exe</NAME>
<NAME name="Tutanota Desktop" regex="false" typeFilter="file">Tutanota Desktop.exe</NAME>
<NAME name="BitLocker" regex="false" typeFilter="all">BitLockerDeviceEncryption.exe</NAME>
<NAME name="certainsafe" regex="false" typeFilter="file">certainsafe.exe</NAME>
<NAME name="CryptoExpert 8" regex="false" typeFilter="file">cexpertcmd.exe</NAME>
<NAME name="CryptoExpert 8" regex="false" typeFilter="file"> cexpert_gui.exe</NAME>
<NAME name="Cryptomator" regex="false" typeFilter="file">Cryptomator.exe</NAME>
<NAME name="Ecrypt(Linux)" regex="true" typeFilter="all">ecryptfs</NAME>
<NAME name="EncFSMP" regex="false" typeFilter="file">EncFSMP.exe</NAME>
<NAME name="Encrypto" regex="false" typeFilter="file">Encrypto.exe</NAME>
<NAME name="Folder Lock" regex="false" typeFilter="file">Folder Lock.exe</NAME>
<NAME name="Gihosoft File Encryption" regex="false" typeFilter="file">GFileEncryption.exe</NAME>
<NAME name="GnuPG" regex="false" typeFilter="file"> gpg.exe</NAME>
<NAME name="Gpg4win" regex="false" typeFilter="file">gdbus.exe</NAME>
<NAME name="KeePass" regex="false" typeFilter="file">KeePass.exe</NAME>
<NAME name="LUKS(Linux)" regex="true" typeFilter="all">luks</NAME>
<NAME name="Proton Bridge" regex="false" typeFilter="file">Desktop-Bridge.exe</NAME>
<NAME name="Tor Browser" regex="false" typeFilter="all">Tor Browser</NAME>
<NAME name="Tutanota Desktop" regex="false" typeFilter="file">Tutanota Desktop.exe</NAME>
<NAME name="VeraCrypt" regex="false" typeFilter="file">VeraCrypt.exe</NAME>
</INTERESTING_FILE_SET>
</INTERESTING_FILE_SETS>

View File

@ -45,7 +45,7 @@
<compile-dependency/>
<run-dependency>
<release-version>10</release-version>
<specification-version>10.19</specification-version>
<specification-version>10.20</specification-version>
</run-dependency>
</dependency>
<dependency>