7084 handle merge conflicts

This commit is contained in:
William Schaefer 2020-12-28 11:08:25 -05:00
commit 6ff945c981
41 changed files with 1322 additions and 531 deletions

View File

@ -89,8 +89,15 @@ public final class IngestJobInfoPanel extends javax.swing.JPanel {
return;
}
if (CURRENT_CASE == Case.Events.valueOf(evt.getPropertyName())) {
// Check whether we have a case open or case close event.
if ((CURRENT_CASE == Case.Events.valueOf(evt.getPropertyName()))) {
if (evt.getNewValue() != null) {
// Case open
refresh();
} else {
// Case close
reset();
}
}
});
}
@ -124,7 +131,7 @@ public final class IngestJobInfoPanel extends javax.swing.JPanel {
*/
private void refresh() {
try {
if (Case.isCaseOpen()) {
if (Case.isCaseOpen()) { // Note - this will generally return true when handling a case close event
SleuthkitCase skCase = Case.getCurrentCaseThrows().getSleuthkitCase();
this.ingestJobs = skCase.getIngestJobs();
setDataSource(selectedDataSource);
@ -139,6 +146,14 @@ public final class IngestJobInfoPanel extends javax.swing.JPanel {
}
}
/**
* Reset the panel.
*/
private void reset() {
this.ingestJobs = new ArrayList<>();
setDataSource(null);
}
@Messages({"IngestJobInfoPanel.IngestJobTableModel.StartTime.header=Start Time",
"IngestJobInfoPanel.IngestJobTableModel.EndTime.header=End Time",
"IngestJobInfoPanel.IngestJobTableModel.IngestStatus.header=Ingest Status"})

View File

@ -52,11 +52,9 @@ import javax.swing.JPanel;
import javax.swing.filechooser.FileNameExtensionFilter;
import javax.swing.table.TableModel;
import javax.swing.table.TableRowSorter;
import org.apache.commons.lang.StringUtils;
import org.joda.time.DateTimeZone;
import org.joda.time.LocalDateTime;
import org.openide.nodes.Node;
import org.openide.util.Exceptions;
import org.openide.util.NbBundle.Messages;
import org.openide.util.lookup.ServiceProvider;
import org.sleuthkit.autopsy.casemodule.Case;
@ -78,7 +76,6 @@ import org.sleuthkit.datamodel.TskException;
import org.sleuthkit.datamodel.SleuthkitCase;
import org.sleuthkit.datamodel.TskData;
import org.sleuthkit.autopsy.centralrepository.datamodel.CentralRepository;
import org.sleuthkit.autopsy.datamodel.BlackboardArtifactNode;
/**
* View correlation results from other cases
@ -469,16 +466,11 @@ public class DataContentViewerOtherCases extends JPanel implements DataContentVi
if (bbArtifact != null && CentralRepository.isEnabled()) {
ret.addAll(CorrelationAttributeUtil.makeCorrAttrsForCorrelation(bbArtifact));
}
boolean isSupported = false;
try {
isSupported = this.file != null && this.file.getSize() > 0 && isDownloadParentSupported(node);
} catch (TskCoreException ex) {
LOGGER.log(Level.WARNING, ex.getMessage(), ex);
}
// we can correlate based on the MD5 if it is enabled
if (isSupported && CentralRepository.isEnabled()) {
if (this.file != null && CentralRepository.isEnabled() && this.file.getSize() > 0) {
try {
List<CorrelationAttributeInstance.Type> artifactTypes = CentralRepository.getInstance().getDefinedCorrelationTypes();
String md5 = this.file.getMd5Hash();
if (md5 != null && !md5.isEmpty() && null != artifactTypes && !artifactTypes.isEmpty()) {
@ -506,7 +498,7 @@ public class DataContentViewerOtherCases extends JPanel implements DataContentVi
LOGGER.log(Level.SEVERE, "Error connecting to DB", ex); // NON-NLS
}
// If EamDb not enabled, get the Files default correlation type to allow Other Occurances to be enabled.
} else if (isSupported) {
} else if (this.file != null && this.file.getSize() > 0) {
String md5 = this.file.getMd5Hash();
if (md5 != null && !md5.isEmpty()) {
try {
@ -525,37 +517,8 @@ public class DataContentViewerOtherCases extends JPanel implements DataContentVi
}
}
}
return ret;
}
/**
* Private helper method to check if the node is an TSK_WEB_DOWNLOAD or
* TSK_WEB_CACHE artifact and if it is, if the file reflects the parent file
* or the downloaded file.
*
* @param node The node to check support for.
*
* @return False if the node is for a Web Cache or a Web Download artifact,
* and that artifact's content file is it's parent.
*
* @throws TskCoreException Unable to retrieve the parent of the artifact in
* this node.
*/
private boolean isDownloadParentSupported(Node node) throws TskCoreException {
if (node instanceof BlackboardArtifactNode) {
BlackboardArtifact theArtifact = ((BlackboardArtifactNode) node).getArtifact();
try {
//disable the content viewer when a download or cached file does not exist instead of displaying its parent
if ((theArtifact.getArtifactTypeID() == BlackboardArtifact.ARTIFACT_TYPE.TSK_WEB_DOWNLOAD.getTypeID()
|| theArtifact.getArtifactTypeID() == BlackboardArtifact.ARTIFACT_TYPE.TSK_WEB_CACHE.getTypeID())
&& this.file.getId() == theArtifact.getParent().getId()) {
return false;
}
} catch (TskCoreException ex) {
throw new TskCoreException(String.format("Error getting parent of artifact with type %s and objID = %d can not confirm content with name %s and objId = %d is not the parent. Other occurences will not correlate on the file.", theArtifact.getArtifactTypeName(), theArtifact.getObjectID(), this.file.getName(), this.file.getId()), ex);
}
}
return true;
return ret;
}
@Messages({"DataContentViewerOtherCases.earliestCaseNotAvailable= Not Enabled."})
@ -738,16 +701,11 @@ public class DataContentViewerOtherCases extends JPanel implements DataContentVi
this.file = this.getAbstractFileFromNode(node);
if (CentralRepository.isEnabled()) {
return !getCorrelationAttributesFromNode(node).isEmpty();
} else if (this.file == null || this.file.getSize() <= 0 || StringUtils.isBlank(file.getMd5Hash())) {
return false;
} else {
return this.file != null
&& this.file.getSize() > 0
&& ((this.file.getMd5Hash() != null) && (!this.file.getMd5Hash().isEmpty()));
}
boolean isSupported = false;
try {
isSupported = isDownloadParentSupported(node);
} catch (TskCoreException ex) {
LOGGER.log(Level.WARNING, ex.getMessage(), ex);
}
return isSupported;
}
@Override

View File

@ -336,7 +336,7 @@ public final class CentralRepoAccount {
normalizedAccountIdentifier = accountIdentifier.toLowerCase();
}
} catch (CorrelationAttributeNormalizationException ex) {
throw new InvalidAccountIDException("Invalid account identifier", ex);
throw new InvalidAccountIDException(String.format("Account id normaization failed, invalid account identifier %s", accountIdentifier), ex);
}
return normalizedAccountIdentifier;

View File

@ -28,3 +28,9 @@ SummaryViewer.contactsLabel.text=Book Entries:
SummaryViewer.accountCountry.text=<account country>
SummaryViewer.fileRefPane.border.title=File References in Current Case
SummaryViewer.selectAccountFileRefLabel.text=<Select a single account to see File References>
SummaryViewer.personaPanel.border.title=Personas
PersonaPanel.personaIDLabel.text=jLabel1
SummaryPersonaPane.noPersonaLabel.text=No personas found
SummaryPersonaPane.messageLabel.text=<Enable Central Repository to create and view personas>
SummaryPersonaPane.createButton.text=Create
PersonaPanel.viewButton.text=View

View File

@ -35,6 +35,8 @@ MessageViewer_viewMessage_all=All
MessageViewer_viewMessage_calllogs=Call Logs
MessageViewer_viewMessage_selected=Selected
MessageViewer_viewMessage_unthreaded=Unthreaded
# {0} - accountIdentifer
SummaryPersonaPane_not_account_in_cr=Unable to find an account with identifier {0} in the Central Repository.
SummaryViewer.countsPanel.border.title=Communications
OutlineViewPanel.messageLabel.text=<Control Disabled>
SummaryViewer.messagesDataLabel.text=messages
@ -52,6 +54,8 @@ SummaryViewer_Device_Account_Description=This account was referenced by a device
SummaryViewer_Fetching_References=<Fetching File References>
SummaryViewer_FileRef_Message=<Select a single account to see File References>
SummaryViewer_FileRefNameColumn_Title=Path
SummaryViewer_Persona_Message=<Enable Central Repository to view Personas>
SummaryViewer_Select_account_for_persona=<Select a single account to see Persona(s)>
SummaryViewer_TabTitle=Summary
ThreadRootMessagePanel.showAllCheckBox.text=Show All Messages
ThreadPane.backButton.text=<---
@ -75,3 +79,9 @@ SummaryViewer.contactsLabel.text=Book Entries:
SummaryViewer.accountCountry.text=<account country>
SummaryViewer.fileRefPane.border.title=File References in Current Case
SummaryViewer.selectAccountFileRefLabel.text=<Select a single account to see File References>
SummaryViewer.personaPanel.border.title=Personas
PersonaPanel.personaIDLabel.text=jLabel1
SummaryPersonaPane.noPersonaLabel.text=No personas found
SummaryPersonaPane.messageLabel.text=<Enable Central Repository to create and view personas>
SummaryPersonaPane.createButton.text=Create
PersonaPanel.viewButton.text=View

View File

@ -0,0 +1,47 @@
<?xml version="1.0" encoding="UTF-8" ?>
<Form version="1.5" maxVersion="1.9" type="org.netbeans.modules.form.forminfo.JPanelFormInfo">
<AuxValues>
<AuxValue name="FormSettings_autoResourcing" type="java.lang.Integer" value="1"/>
<AuxValue name="FormSettings_autoSetComponentName" type="java.lang.Boolean" value="false"/>
<AuxValue name="FormSettings_generateFQN" type="java.lang.Boolean" value="true"/>
<AuxValue name="FormSettings_generateMnemonicsCode" type="java.lang.Boolean" value="true"/>
<AuxValue name="FormSettings_i18nAutoMode" type="java.lang.Boolean" value="true"/>
<AuxValue name="FormSettings_layoutCodeTarget" type="java.lang.Integer" value="1"/>
<AuxValue name="FormSettings_listenerGenerationStyle" type="java.lang.Integer" value="0"/>
<AuxValue name="FormSettings_variablesLocal" type="java.lang.Boolean" value="false"/>
<AuxValue name="FormSettings_variablesModifier" type="java.lang.Integer" value="2"/>
<AuxValue name="designerSize" type="java.awt.Dimension" value="-84,-19,0,5,115,114,0,18,106,97,118,97,46,97,119,116,46,68,105,109,101,110,115,105,111,110,65,-114,-39,-41,-84,95,68,20,2,0,2,73,0,6,104,101,105,103,104,116,73,0,5,119,105,100,116,104,120,112,0,0,0,59,0,0,0,-8"/>
</AuxValues>
<Layout class="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout"/>
<SubComponents>
<Component class="javax.swing.JLabel" name="personaIDLabel">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/communications/relationships/Bundle.properties" key="PersonaPanel.personaIDLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
</Properties>
<Constraints>
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
<GridBagConstraints gridX="-1" gridY="-1" gridWidth="1" gridHeight="1" fill="0" ipadX="0" ipadY="0" insetsTop="0" insetsLeft="5" insetsBottom="0" insetsRight="0" anchor="17" weightX="0.0" weightY="0.0"/>
</Constraint>
</Constraints>
</Component>
<Component class="javax.swing.JButton" name="viewButton">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/communications/relationships/Bundle.properties" key="PersonaPanel.viewButton.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
<Property name="margin" type="java.awt.Insets" editor="org.netbeans.beaninfo.editors.InsetsEditor">
<Insets value="[0, 5, 0, 5]"/>
</Property>
</Properties>
<Constraints>
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
<GridBagConstraints gridX="-1" gridY="-1" gridWidth="1" gridHeight="1" fill="0" ipadX="0" ipadY="0" insetsTop="0" insetsLeft="5" insetsBottom="0" insetsRight="0" anchor="17" weightX="1.0" weightY="0.0"/>
</Constraint>
</Constraints>
</Component>
</SubComponents>
</Form>

View File

@ -0,0 +1,115 @@
/*
* Autopsy Forensic Browser
*
* Copyright 2020 Basis Technology Corp.
* Contact: carrier <at> sleuthkit <dot> org
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obt ain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.sleuthkit.autopsy.communications.relationships;
import java.awt.Dimension;
import javax.swing.JButton;
import org.sleuthkit.autopsy.centralrepository.datamodel.Persona;
/**
*
* Panel to show a single persona with a button for viewing persona details.
*/
public class PersonaPanel extends javax.swing.JPanel {
private static final long serialVersionUID = 1L;
private final Persona persona;
/**
* Creates new form PersonaPanel
*/
PersonaPanel(Persona persona) {
initComponents();
this.persona = persona;
personaIDLabel.setText(persona.getName());
}
/**
* Returns the persona displayed by this panel.
*
* @return
*/
Persona getPersona() {
return persona;
}
/**
* Returns the preferred width for the given persona label.
*
* @return
*/
int getPersonaLabelPreferedWidth() {
return personaIDLabel.getPreferredSize().width;
}
/**
* Sets the preferred width for the persona name label.
*
* @param width
*/
void setPersonalLabelPreferredWidth(int width) {
Dimension currentDim = personaIDLabel.getPreferredSize();
personaIDLabel.setPreferredSize(new Dimension(Math.max(currentDim.width, width), currentDim.height));
}
/**
* Returns the View button for this panel.
*
* @return
*/
JButton getViewButton() {
return viewButton;
}
/**
* This method is called from within the constructor to initialize the form.
* WARNING: Do NOT modify this code. The content of this method is always
* regenerated by the Form Editor.
*/
@SuppressWarnings("unchecked")
// <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
private void initComponents() {
java.awt.GridBagConstraints gridBagConstraints;
personaIDLabel = new javax.swing.JLabel();
viewButton = new javax.swing.JButton();
setLayout(new java.awt.GridBagLayout());
org.openide.awt.Mnemonics.setLocalizedText(personaIDLabel, org.openide.util.NbBundle.getMessage(PersonaPanel.class, "PersonaPanel.personaIDLabel.text")); // NOI18N
gridBagConstraints = new java.awt.GridBagConstraints();
gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST;
gridBagConstraints.insets = new java.awt.Insets(0, 5, 0, 0);
add(personaIDLabel, gridBagConstraints);
org.openide.awt.Mnemonics.setLocalizedText(viewButton, org.openide.util.NbBundle.getMessage(PersonaPanel.class, "PersonaPanel.viewButton.text")); // NOI18N
viewButton.setMargin(new java.awt.Insets(0, 5, 0, 5));
gridBagConstraints = new java.awt.GridBagConstraints();
gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST;
gridBagConstraints.weightx = 1.0;
gridBagConstraints.insets = new java.awt.Insets(0, 5, 0, 0);
add(viewButton, gridBagConstraints);
}// </editor-fold>//GEN-END:initComponents
// Variables declaration - do not modify//GEN-BEGIN:variables
private javax.swing.JLabel personaIDLabel;
private javax.swing.JButton viewButton;
// End of variables declaration//GEN-END:variables
}

View File

@ -0,0 +1,146 @@
/*
* Autopsy Forensic Browser
*
* Copyright 2020 Basis Technology Corp.
* Contact: carrier <at> sleuthkit <dot> org
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obt ain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.sleuthkit.autopsy.communications.relationships;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.logging.Level;
import javax.swing.SwingWorker;
import org.sleuthkit.autopsy.casemodule.Case;
import org.sleuthkit.autopsy.centralrepository.datamodel.CentralRepoAccount;
import org.sleuthkit.autopsy.centralrepository.datamodel.CentralRepository;
import org.sleuthkit.autopsy.centralrepository.datamodel.Persona;
import org.sleuthkit.autopsy.centralrepository.datamodel.PersonaAccount;
import org.sleuthkit.autopsy.coreutils.Logger;
import org.sleuthkit.datamodel.Account;
import org.sleuthkit.datamodel.AccountFileInstance;
import org.sleuthkit.datamodel.InvalidAccountIDException;
/**
* Runnable SwingWorker for gather the data that the Summary panel needs.
*/
class SummaryPanelWorker extends SwingWorker<SummaryPanelWorker.SummaryWorkerResults, Void> {
private final static Logger logger = Logger.getLogger(SummaryPanelWorker.class.getName());
private final Account account;
// Construct a instance
SummaryPanelWorker(Account account) {
this.account = account;
}
/**
* Returns the account the worker is gathering data for.
*
* @return
*/
Account getAccount() {
return account;
}
@Override
protected SummaryWorkerResults doInBackground() throws Exception {
CentralRepoAccount crAccount = null;
List<String> stringList = new ArrayList<>();
List<AccountFileInstance> accountFileInstanceList = Case.getCurrentCase().getSleuthkitCase().getCommunicationsManager().getAccountFileInstances(account);
for (AccountFileInstance instance : accountFileInstanceList) {
stringList.add(instance.getFile().getUniquePath());
}
List<Persona> personaList = new ArrayList<>();
if (CentralRepository.isEnabled()) {
Collection<PersonaAccount> personaAccountList = PersonaAccount.getPersonaAccountsForAccount(account);
PersonaAccount.getPersonaAccountsForAccount(account);
for (PersonaAccount pAccount : personaAccountList) {
personaList.add(pAccount.getPersona());
}
try {
crAccount = CentralRepository.getInstance().getAccount(CentralRepository.getInstance().getAccountTypeByName(account.getAccountType().getTypeName()), account.getTypeSpecificID());
} catch (InvalidAccountIDException unused) {
// This was probably caused to a phone number not making
// threw the normalization.
logger.log(Level.WARNING, String.format("Exception thrown from CR getAccount for account %s (%d)", account.getTypeSpecificID(), account.getAccountID()));
}
}
return new SummaryWorkerResults(stringList, personaList, crAccount);
}
/**
* Wraps the results of the worker for easy of returning and usage by the
* SummaryViewer.
*/
final static class SummaryWorkerResults {
private final List<String> accountFileInstancePaths;
private final List<Persona> personaList;
private final CentralRepoAccount centralRepoAccount;
/**
* Constructor.
*
* @param accountFileInstancePaths List of instance paths.
* @param personaList List of personas for the account
* @param centralRepoAccount CentralRepoAccount for the given
* account, maybe null if CR is not
* enabled.
*/
SummaryWorkerResults(List<String> accountFileInstancePaths, List<Persona> personaList, CentralRepoAccount centralRepoAccount) {
this.accountFileInstancePaths = accountFileInstancePaths;
this.personaList = personaList;
this.centralRepoAccount = centralRepoAccount;
}
/**
* Returns the list of instance paths for the account given to the
* worker.
*
* @return
*/
List<String> getPaths() {
return accountFileInstancePaths;
}
/**
* Returns the list of personas found for the account given to the
* worker. This list maybe empty if none were found or cr is not
* enabled.
*
* @return
*/
List<Persona> getPersonaList() {
return personaList;
}
/**
* Return the cr account for the account given to the worker. This maybe
* null if the cr was not enabled.
*
* @return
*/
CentralRepoAccount getCRAccount() {
return centralRepoAccount;
}
}
}

View File

@ -0,0 +1,104 @@
<?xml version="1.0" encoding="UTF-8" ?>
<Form version="1.5" maxVersion="1.9" type="org.netbeans.modules.form.forminfo.JPanelFormInfo">
<AuxValues>
<AuxValue name="FormSettings_autoResourcing" type="java.lang.Integer" value="1"/>
<AuxValue name="FormSettings_autoSetComponentName" type="java.lang.Boolean" value="false"/>
<AuxValue name="FormSettings_generateFQN" type="java.lang.Boolean" value="true"/>
<AuxValue name="FormSettings_generateMnemonicsCode" type="java.lang.Boolean" value="true"/>
<AuxValue name="FormSettings_i18nAutoMode" type="java.lang.Boolean" value="true"/>
<AuxValue name="FormSettings_layoutCodeTarget" type="java.lang.Integer" value="1"/>
<AuxValue name="FormSettings_listenerGenerationStyle" type="java.lang.Integer" value="0"/>
<AuxValue name="FormSettings_variablesLocal" type="java.lang.Boolean" value="false"/>
<AuxValue name="FormSettings_variablesModifier" type="java.lang.Integer" value="2"/>
<AuxValue name="designerSize" type="java.awt.Dimension" value="-84,-19,0,5,115,114,0,18,106,97,118,97,46,97,119,116,46,68,105,109,101,110,115,105,111,110,65,-114,-39,-41,-84,95,68,20,2,0,2,73,0,6,104,101,105,103,104,116,73,0,5,119,105,100,116,104,120,112,0,0,1,16,0,0,2,121"/>
</AuxValues>
<Layout class="org.netbeans.modules.form.compat2.layouts.DesignCardLayout"/>
<SubComponents>
<Container class="javax.swing.JScrollPane" name="personaScrollPane">
<Properties>
<Property name="border" type="javax.swing.border.Border" editor="org.netbeans.modules.form.editors2.BorderEditor">
<Border info="null"/>
</Property>
</Properties>
<Constraints>
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignCardLayout" value="org.netbeans.modules.form.compat2.layouts.DesignCardLayout$CardConstraintsDescription">
<CardConstraints cardName="persona"/>
</Constraint>
</Constraints>
<Layout class="org.netbeans.modules.form.compat2.layouts.support.JScrollPaneSupportLayout"/>
</Container>
<Container class="javax.swing.JPanel" name="messagePane">
<Constraints>
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignCardLayout" value="org.netbeans.modules.form.compat2.layouts.DesignCardLayout$CardConstraintsDescription">
<CardConstraints cardName="message"/>
</Constraint>
</Constraints>
<Layout class="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout"/>
<SubComponents>
<Component class="javax.swing.JLabel" name="messageLabel">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/communications/relationships/Bundle.properties" key="SummaryPersonaPane.messageLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
<Property name="enabled" type="boolean" value="false"/>
</Properties>
<Constraints>
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
<GridBagConstraints gridX="0" gridY="0" gridWidth="1" gridHeight="1" fill="2" ipadX="0" ipadY="0" insetsTop="0" insetsLeft="0" insetsBottom="0" insetsRight="0" anchor="10" weightX="0.0" weightY="1.0"/>
</Constraint>
</Constraints>
</Component>
</SubComponents>
</Container>
<Container class="javax.swing.JPanel" name="createPersonaPanel">
<Properties>
<Property name="preferredSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[200, 100]"/>
</Property>
</Properties>
<Constraints>
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignCardLayout" value="org.netbeans.modules.form.compat2.layouts.DesignCardLayout$CardConstraintsDescription">
<CardConstraints cardName="create"/>
</Constraint>
</Constraints>
<Layout class="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout"/>
<SubComponents>
<Component class="javax.swing.JLabel" name="noPersonaLabel">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/communications/relationships/Bundle.properties" key="SummaryPersonaPane.noPersonaLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
</Properties>
<Constraints>
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
<GridBagConstraints gridX="0" gridY="0" gridWidth="1" gridHeight="1" fill="0" ipadX="0" ipadY="0" insetsTop="7" insetsLeft="5" insetsBottom="0" insetsRight="0" anchor="18" weightX="0.0" weightY="1.0"/>
</Constraint>
</Constraints>
</Component>
<Component class="javax.swing.JButton" name="createButton">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/communications/relationships/Bundle.properties" key="SummaryPersonaPane.createButton.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
<Property name="margin" type="java.awt.Insets" editor="org.netbeans.beaninfo.editors.InsetsEditor">
<Insets value="[0, 5, 0, 5]"/>
</Property>
</Properties>
<Events>
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="createButtonActionPerformed"/>
</Events>
<Constraints>
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
<GridBagConstraints gridX="1" gridY="0" gridWidth="1" gridHeight="2" fill="0" ipadX="0" ipadY="0" insetsTop="5" insetsLeft="5" insetsBottom="0" insetsRight="0" anchor="18" weightX="1.0" weightY="1.0"/>
</Constraint>
</Constraints>
</Component>
</SubComponents>
</Container>
</SubComponents>
</Form>

View File

@ -0,0 +1,295 @@
/*
* Autopsy Forensic Browser
*
* Copyright 2020 Basis Technology Corp.
* Contact: carrier <at> sleuthkit <dot> org
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obt ain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.sleuthkit.autopsy.communications.relationships;
import java.awt.CardLayout;
import java.awt.Component;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.logging.Level;
import javax.swing.Box;
import javax.swing.JButton;
import javax.swing.JPanel;
import org.openide.util.NbBundle;
import org.sleuthkit.autopsy.centralrepository.datamodel.CentralRepoAccount;
import org.sleuthkit.autopsy.centralrepository.datamodel.CentralRepoException;
import org.sleuthkit.autopsy.centralrepository.datamodel.Persona;
import org.sleuthkit.autopsy.centralrepository.datamodel.PersonaAccount;
import org.sleuthkit.autopsy.centralrepository.persona.PersonaDetailsDialog;
import org.sleuthkit.autopsy.centralrepository.persona.PersonaDetailsDialogCallback;
import org.sleuthkit.autopsy.centralrepository.persona.PersonaDetailsMode;
import org.sleuthkit.autopsy.centralrepository.persona.PersonaDetailsPanel;
import org.sleuthkit.autopsy.coreutils.Logger;
import org.sleuthkit.datamodel.Account;
/**
* Panel to show the Personas for a given account. That is apart SummaryViewer.
*/
public final class SummaryPersonaPane extends javax.swing.JPanel {
private static final long serialVersionUID = 1L;
private final static Logger logger = Logger.getLogger(SummaryPersonaPane.class.getName());
private final Map<Component, Persona> personaMap;
private final ViewButtonHandler viewButtonHandler = new ViewButtonHandler();
private CentralRepoAccount currentCRAccount = null;
private Account currentAccount = null;
/**
* Creates new form SummaryPersonaPane
*/
SummaryPersonaPane() {
initComponents();
personaScrollPane.setViewportView(new JPanel());
personaMap = new HashMap<>();
}
/**
* Clear the persona list.
*/
void clearList() {
personaScrollPane.setViewportView(new JPanel());
personaMap.clear();
}
/**
* Show the message panel.
*/
void showMessagePanel() {
CardLayout layout = (CardLayout) getLayout();
layout.show(this, "message");
}
/**
* Set the message that appears when the message panel is visible.
*
* @param message Message to show.
*/
void setMessage(String message) {
messageLabel.setText(message);
}
/**
* Update the list of personas to the new given list.
*
* @param personaList New list of personas to show
*/
void updatePersonaList(Account account, CentralRepoAccount crAccount, List<Persona> personaList) {
JPanel panel = new JPanel();
currentCRAccount = crAccount;
currentAccount = account;
CardLayout layout = (CardLayout) getLayout();
if (personaList.isEmpty()) {
layout.show(this, "create");
} else {
panel.setLayout(new GridLayout(personaList.size() + 1, 1));
int maxWidth = 0;
List<PersonaPanel> panelList = new ArrayList<>();
for (Persona persona : personaList) {
PersonaPanel personaPanel = new PersonaPanel(persona);
JButton viewButton = personaPanel.getViewButton();
panel.add(personaPanel);
personaMap.put(viewButton, persona);
viewButton.addActionListener(viewButtonHandler);
panelList.add(personaPanel);
maxWidth = Math.max(personaPanel.getPersonaLabelPreferedWidth(), maxWidth);
}
//Set the preferred width of the labeles to the buttons line up.
if (panelList.size() > 1) {
for (PersonaPanel ppanel : panelList) {
ppanel.setPersonalLabelPreferredWidth(maxWidth);
}
}
panel.add(Box.createVerticalGlue());
personaScrollPane.setViewportView(panel);
layout.show(this, "persona");
}
}
/**
* ActionListener to handle the launching of the view dialog for the given
* persona.
*/
final private class ViewButtonHandler implements ActionListener {
@Override
public void actionPerformed(ActionEvent e) {
Persona persona = personaMap.get((Component) e.getSource());
new PersonaDetailsDialog(SummaryPersonaPane.this,
PersonaDetailsMode.VIEW, persona, new PersonaViewCallbackImpl());
}
}
/**
* Callback method for the view mode of the PersonaDetailsDialog
*/
private final class PersonaViewCallbackImpl implements PersonaDetailsDialogCallback {
@Override
public void callback(Persona persona) {
// nothing to do
}
}
/**
* Callback class to handle the creation of a new person for the given
* account
*/
private final class PersonaCreateCallbackImpl implements PersonaDetailsDialogCallback {
@Override
public void callback(Persona persona) {
if (persona != null) {
List<Persona> list = new ArrayList<>();
list.add(persona);
CentralRepoAccount crAccount = null;
Collection<PersonaAccount> personaAccounts = null;
try {
personaAccounts = persona.getPersonaAccounts();
} catch (CentralRepoException ex) {
logger.log(Level.WARNING, String.format("Failed to get cr account from person %s (%d)", persona.getName(), persona.getId()), ex);
}
if (personaAccounts != null) {
Iterator<PersonaAccount> iterator = personaAccounts.iterator();
if (iterator.hasNext()) {
crAccount = iterator.next().getAccount();
}
}
updatePersonaList(currentAccount, crAccount, list);
}
}
}
/**
* This method is called from within the constructor to initialize the form.
* WARNING: Do NOT modify this code. The content of this method is always
* regenerated by the Form Editor.
*/
@SuppressWarnings("unchecked")
// <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
private void initComponents() {
java.awt.GridBagConstraints gridBagConstraints;
personaScrollPane = new javax.swing.JScrollPane();
messagePane = new javax.swing.JPanel();
messageLabel = new javax.swing.JLabel();
createPersonaPanel = new javax.swing.JPanel();
noPersonaLabel = new javax.swing.JLabel();
createButton = new javax.swing.JButton();
setLayout(new java.awt.CardLayout());
personaScrollPane.setBorder(null);
add(personaScrollPane, "persona");
messagePane.setLayout(new java.awt.GridBagLayout());
org.openide.awt.Mnemonics.setLocalizedText(messageLabel, org.openide.util.NbBundle.getMessage(SummaryPersonaPane.class, "SummaryPersonaPane.messageLabel.text")); // NOI18N
messageLabel.setEnabled(false);
gridBagConstraints = new java.awt.GridBagConstraints();
gridBagConstraints.gridx = 0;
gridBagConstraints.gridy = 0;
gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
gridBagConstraints.weighty = 1.0;
messagePane.add(messageLabel, gridBagConstraints);
add(messagePane, "message");
createPersonaPanel.setPreferredSize(new java.awt.Dimension(200, 100));
createPersonaPanel.setLayout(new java.awt.GridBagLayout());
org.openide.awt.Mnemonics.setLocalizedText(noPersonaLabel, org.openide.util.NbBundle.getMessage(SummaryPersonaPane.class, "SummaryPersonaPane.noPersonaLabel.text")); // NOI18N
gridBagConstraints = new java.awt.GridBagConstraints();
gridBagConstraints.gridx = 0;
gridBagConstraints.gridy = 0;
gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
gridBagConstraints.weighty = 1.0;
gridBagConstraints.insets = new java.awt.Insets(7, 5, 0, 0);
createPersonaPanel.add(noPersonaLabel, gridBagConstraints);
org.openide.awt.Mnemonics.setLocalizedText(createButton, org.openide.util.NbBundle.getMessage(SummaryPersonaPane.class, "SummaryPersonaPane.createButton.text")); // NOI18N
createButton.setMargin(new java.awt.Insets(0, 5, 0, 5));
createButton.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
createButtonActionPerformed(evt);
}
});
gridBagConstraints = new java.awt.GridBagConstraints();
gridBagConstraints.gridx = 1;
gridBagConstraints.gridy = 0;
gridBagConstraints.gridheight = 2;
gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
gridBagConstraints.weightx = 1.0;
gridBagConstraints.weighty = 1.0;
gridBagConstraints.insets = new java.awt.Insets(5, 5, 0, 0);
createPersonaPanel.add(createButton, gridBagConstraints);
add(createPersonaPanel, "create");
}// </editor-fold>//GEN-END:initComponents
@NbBundle.Messages({
"# {0} - accountIdentifer",
"SummaryPersonaPane_not_account_in_cr=Unable to find an account with identifier {0} in the Central Repository."
})
private void createButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_createButtonActionPerformed
PersonaDetailsDialog createPersonaDialog = new PersonaDetailsDialog(SummaryPersonaPane.this,
PersonaDetailsMode.CREATE, null, new PersonaCreateCallbackImpl(), false);
// Pre populate the persona name and accounts if we have them.
PersonaDetailsPanel personaPanel = createPersonaDialog.getDetailsPanel();
if (currentCRAccount != null) {
personaPanel.addAccount(currentCRAccount, "", Persona.Confidence.HIGH);
} else {
createPersonaDialog.setStartupPopupMessage(Bundle.SummaryPersonaPane_not_account_in_cr(currentAccount.getTypeSpecificID()));
}
personaPanel.setPersonaName(currentAccount.getTypeSpecificID());
// display the dialog now
createPersonaDialog.display();
}//GEN-LAST:event_createButtonActionPerformed
// Variables declaration - do not modify//GEN-BEGIN:variables
private javax.swing.JButton createButton;
private javax.swing.JPanel createPersonaPanel;
private javax.swing.JLabel messageLabel;
private javax.swing.JPanel messagePane;
private javax.swing.JLabel noPersonaLabel;
private javax.swing.JScrollPane personaScrollPane;
// End of variables declaration//GEN-END:variables
}

View File

@ -265,7 +265,7 @@
</Properties>
<Constraints>
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
<GridBagConstraints gridX="0" gridY="4" gridWidth="1" gridHeight="1" fill="1" ipadX="0" ipadY="0" insetsTop="9" insetsLeft="0" insetsBottom="0" insetsRight="0" anchor="18" weightX="1.0" weightY="1.0"/>
<GridBagConstraints gridX="0" gridY="5" gridWidth="1" gridHeight="1" fill="1" ipadX="0" ipadY="0" insetsTop="9" insetsLeft="0" insetsBottom="0" insetsRight="0" anchor="18" weightX="1.0" weightY="1.0"/>
</Constraint>
</Constraints>
</Component>
@ -281,7 +281,7 @@
</Properties>
<Constraints>
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
<GridBagConstraints gridX="0" gridY="3" gridWidth="1" gridHeight="1" fill="1" ipadX="0" ipadY="0" insetsTop="0" insetsLeft="0" insetsBottom="0" insetsRight="0" anchor="18" weightX="0.0" weightY="1.0"/>
<GridBagConstraints gridX="0" gridY="4" gridWidth="1" gridHeight="1" fill="1" ipadX="0" ipadY="0" insetsTop="0" insetsLeft="0" insetsBottom="0" insetsRight="0" anchor="18" weightX="0.0" weightY="1.0"/>
</Constraint>
</Constraints>
@ -363,5 +363,32 @@
</Container>
</SubComponents>
</Container>
<Container class="javax.swing.JPanel" name="personaPanel">
<Properties>
<Property name="border" type="javax.swing.border.Border" editor="org.netbeans.modules.form.editors2.BorderEditor">
<Border info="org.netbeans.modules.form.compat2.border.TitledBorderInfo">
<TitledBorder title="Personas">
<ResourceString PropertyName="titleX" bundle="org/sleuthkit/autopsy/communications/relationships/Bundle.properties" key="SummaryViewer.personaPanel.border.title" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</TitledBorder>
</Border>
</Property>
<Property name="minimumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[35, 75]"/>
</Property>
<Property name="preferredSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[112, 75]"/>
</Property>
</Properties>
<AuxValues>
<AuxValue name="JavaCodeGenerator_CreateCodeCustom" type="java.lang.String" value="new SummaryPersonaPane()"/>
</AuxValues>
<Constraints>
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
<GridBagConstraints gridX="-1" gridY="3" gridWidth="1" gridHeight="1" fill="2" ipadX="0" ipadY="0" insetsTop="0" insetsLeft="0" insetsBottom="0" insetsRight="0" anchor="10" weightX="0.0" weightY="0.0"/>
</Constraint>
</Constraints>
<Layout class="org.netbeans.modules.form.compat2.layouts.DesignFlowLayout"/>
</Container>
</SubComponents>
</Form>

View File

@ -1,7 +1,7 @@
/*
* Autopsy Forensic Browser
*
* Copyright 2019 Basis Technology Corp.
* Copyright 2019-2020 Basis Technology Corp.
* Contact: carrier <at> sleuthkit <dot> org
*
* Licensed under the Apache License, Version 2.0 (the "License");
@ -19,13 +19,11 @@
package org.sleuthkit.autopsy.communications.relationships;
import java.awt.CardLayout;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ExecutionException;
import java.util.logging.Level;
import javax.swing.DefaultListModel;
import javax.swing.JPanel;
import javax.swing.SwingWorker;
import org.netbeans.swing.outline.DefaultOutlineModel;
import org.netbeans.swing.outline.Outline;
import org.openide.explorer.view.OutlineView;
@ -33,11 +31,10 @@ import org.openide.nodes.AbstractNode;
import org.openide.nodes.Children;
import org.openide.util.Lookup;
import org.openide.util.NbBundle.Messages;
import org.sleuthkit.autopsy.casemodule.Case;
import org.sleuthkit.datamodel.Account;
import org.sleuthkit.autopsy.centralrepository.datamodel.CentralRepository;
import org.sleuthkit.autopsy.centralrepository.datamodel.Persona;
import org.sleuthkit.autopsy.coreutils.Logger;
import org.sleuthkit.datamodel.AccountFileInstance;
/**
* Account Summary View Panel. This panel shows a list of various counts related
@ -47,6 +44,8 @@ import org.sleuthkit.datamodel.AccountFileInstance;
*/
public class SummaryViewer extends javax.swing.JPanel implements RelationshipsViewer {
private static final long serialVersionUID = 1L;
private final Lookup lookup;
private final DefaultListModel<String> fileRefListModel;
@ -62,7 +61,8 @@ public class SummaryViewer extends javax.swing.JPanel implements RelationshipsVi
"SummaryViewer_Device_Account_Description=This account was referenced by a device in the case.",
"SummaryViewer_Account_Description=This account represents a device in the case.",
"SummaryViewer_Account_Description_MuliSelect=Summary information is not available when multiple accounts are selected.",
"SummaryViewer_Country_Code=Country: "
"SummaryViewer_Country_Code=Country: ",
"SummaryViewer_Select_account_for_persona=<Select a single account to see Persona(s)>"
})
/**
@ -85,6 +85,8 @@ public class SummaryViewer extends javax.swing.JPanel implements RelationshipsVi
clearControls();
caseReferencesPanel.hideOutlineView(Bundle.SummaryViewer_CentralRepository_Message());
((SummaryPersonaPane)personaPanel).setMessage(Bundle.SummaryViewer_Select_account_for_persona());
((SummaryPersonaPane)personaPanel).showMessagePanel();
}
@Override
@ -153,7 +155,7 @@ public class SummaryViewer extends javax.swing.JPanel implements RelationshipsVi
caseReferencesPanel.setNode(new AbstractNode(Children.create(new CorrelationCaseChildNodeFactory(info.getAccounts()), true)));
updateFileReferences(account);
updateOtherAccountInfo(account);
setEnabled(true);
}
@ -202,24 +204,17 @@ public class SummaryViewer extends javax.swing.JPanel implements RelationshipsVi
}
@Messages({
"SummaryViewer_Fetching_References=<Fetching File References>"
"SummaryViewer_Fetching_References=<Fetching File References>",
"SummaryViewer_Persona_Message=<Enable Central Repository to view Personas>"
})
private void updateFileReferences(final Account account) {
SwingWorker<List<String>, Void> worker = new SwingWorker<List<String>, Void>() {
@Override
protected List<String> doInBackground() throws Exception {
List<String> stringList = new ArrayList<>();
List<AccountFileInstance> accountFileInstanceList = Case.getCurrentCase().getSleuthkitCase().getCommunicationsManager().getAccountFileInstances(account);
for (AccountFileInstance instance : accountFileInstanceList) {
stringList.add(instance.getFile().getUniquePath());
}
return stringList;
}
private void updateOtherAccountInfo(final Account account) {
SummaryPanelWorker worker = new SummaryPanelWorker(account) {
@Override
protected void done() {
try {
List<String> fileRefList = get();
SummaryPanelWorker.SummaryWorkerResults results = get();
List<String> fileRefList = results.getPaths();
fileRefList.forEach(value -> {
fileRefListModel.addElement(value);
@ -228,8 +223,18 @@ public class SummaryViewer extends javax.swing.JPanel implements RelationshipsVi
CardLayout cardLayout = (CardLayout) fileRefPane.getLayout();
cardLayout.show(fileRefPane, "listPanelCard");
List<Persona> personaList = results.getPersonaList();
if (CentralRepository.isEnabled()) {
((SummaryPersonaPane) personaPanel).updatePersonaList(account, results.getCRAccount(), personaList);
} else {
((SummaryPersonaPane) personaPanel).setMessage("Bundle.SummaryViewer_Persona_Message()");
((SummaryPersonaPane) personaPanel).showMessagePanel();
}
} catch (InterruptedException | ExecutionException ex) {
logger.log(Level.WARNING, String.format(("Failed to get file references for account: %d"), account.getAccountID()), ex);
logger.log(Level.WARNING, String.format(("Failed to get data for account: %d"), account.getAccountID()), ex);
}
}
};
@ -273,6 +278,7 @@ public class SummaryViewer extends javax.swing.JPanel implements RelationshipsVi
fileRefList = new javax.swing.JList<>();
javax.swing.JPanel selectAccountPane = new javax.swing.JPanel();
selectAccountFileRefLabel = new javax.swing.JLabel();
personaPanel = new SummaryPersonaPane();
setLayout(new java.awt.GridBagLayout());
@ -430,7 +436,7 @@ public class SummaryViewer extends javax.swing.JPanel implements RelationshipsVi
caseReferencesPanel.setBorder(javax.swing.BorderFactory.createTitledBorder(org.openide.util.NbBundle.getMessage(SummaryViewer.class, "SummaryViewer.caseReferencesPanel.border.title"))); // NOI18N
gridBagConstraints = new java.awt.GridBagConstraints();
gridBagConstraints.gridx = 0;
gridBagConstraints.gridy = 4;
gridBagConstraints.gridy = 5;
gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH;
gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
gridBagConstraints.weightx = 1.0;
@ -464,11 +470,19 @@ public class SummaryViewer extends javax.swing.JPanel implements RelationshipsVi
gridBagConstraints = new java.awt.GridBagConstraints();
gridBagConstraints.gridx = 0;
gridBagConstraints.gridy = 3;
gridBagConstraints.gridy = 4;
gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH;
gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
gridBagConstraints.weighty = 1.0;
add(fileRefPane, gridBagConstraints);
personaPanel.setBorder(javax.swing.BorderFactory.createTitledBorder(org.openide.util.NbBundle.getMessage(SummaryViewer.class, "SummaryViewer.personaPanel.border.title"))); // NOI18N
personaPanel.setMinimumSize(new java.awt.Dimension(35, 75));
personaPanel.setPreferredSize(new java.awt.Dimension(112, 75));
gridBagConstraints = new java.awt.GridBagConstraints();
gridBagConstraints.gridy = 3;
gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
add(personaPanel, gridBagConstraints);
}// </editor-fold>//GEN-END:initComponents
@ -489,6 +503,7 @@ public class SummaryViewer extends javax.swing.JPanel implements RelationshipsVi
private javax.swing.JPanel fileRefPane;
private javax.swing.JLabel messagesDataLabel;
private javax.swing.JLabel messagesLabel;
private javax.swing.JPanel personaPanel;
private javax.swing.JLabel referencesDataLabel;
private javax.swing.JLabel referencesLabel;
private javax.swing.JLabel selectAccountFileRefLabel;

View File

@ -28,11 +28,8 @@ import org.openide.util.NbBundle;
import org.openide.util.lookup.ServiceProvider;
import org.sleuthkit.autopsy.corecomponentinterfaces.DataContentViewer;
import org.sleuthkit.autopsy.coreutils.Logger;
import org.sleuthkit.autopsy.datamodel.BlackboardArtifactNode;
import org.sleuthkit.autopsy.modules.filetypeid.FileTypeDetector;
import org.sleuthkit.datamodel.AbstractFile;
import org.sleuthkit.datamodel.BlackboardArtifact;
import org.sleuthkit.datamodel.TskCoreException;
/**
* Generic Application content viewer
@ -85,7 +82,8 @@ public class FileViewer extends javax.swing.JPanel implements DataContentViewer
*
* @param file
*
* @return FileTypeViewer, null if no known content viewer supports the file
* @return FileTypeViewer, null if no known content viewer supports the
* file
*/
private FileTypeViewer getSupportingViewer(AbstractFile file) {
FileTypeViewer viewer = mimeTypeToViewerMap.get(file.getMIMEType());
@ -115,7 +113,7 @@ public class FileViewer extends javax.swing.JPanel implements DataContentViewer
resetComponent();
if (selectedNode == null || !isSupported(selectedNode)) {
if (selectedNode == null) {
return;
}
@ -195,21 +193,7 @@ public class FileViewer extends javax.swing.JPanel implements DataContentViewer
if ((aFile == null) || (aFile.isDir())) {
return false;
}
if (node instanceof BlackboardArtifactNode) {
BlackboardArtifact theArtifact = ((BlackboardArtifactNode) node).getArtifact();
//disable the content viewer when a download or cached file does not exist instead of displaying its parent
try {
if ((theArtifact.getArtifactTypeID() == BlackboardArtifact.ARTIFACT_TYPE.TSK_WEB_DOWNLOAD.getTypeID()
|| theArtifact.getArtifactTypeID() == BlackboardArtifact.ARTIFACT_TYPE.TSK_WEB_CACHE.getTypeID())
&& aFile.getId() == theArtifact.getParent().getId()) {
return false;
}
} catch (TskCoreException ex) {
LOGGER.log(Level.WARNING, String.format("Error getting parent of artifact with type %s and objID = %d can not confirm file with name %s and objId = %d is not the parent. File content viewer will not be supported.",
theArtifact.getArtifactTypeName(), theArtifact.getObjectID(), aFile.getName(), aFile.getId()), ex);
return false;
}
}
String mimeType = aFile.getMIMEType();
if (Strings.isNullOrEmpty(mimeType)) {
LOGGER.log(Level.INFO, "Mimetype not known for file: {0}", aFile.getName()); //NON-NLS

View File

@ -29,7 +29,6 @@ import org.openide.util.lookup.ServiceProvider;
import org.sleuthkit.autopsy.corecomponentinterfaces.DataContentViewer;
import org.sleuthkit.autopsy.datamodel.ContentUtils;
import org.sleuthkit.autopsy.coreutils.Logger;
import org.sleuthkit.autopsy.datamodel.BlackboardArtifactNode;
import org.sleuthkit.datamodel.AbstractFile;
import org.sleuthkit.datamodel.BlackboardArtifact;
import org.sleuthkit.datamodel.BlackboardArtifact.ARTIFACT_TYPE;
@ -149,10 +148,6 @@ public class Metadata extends javax.swing.JPanel implements DataContentViewer {
"Metadata.nodeText.none=None"})
@Override
public void setNode(Node node) {
if ((node == null) || (!isSupported(node))) {
resetComponent();
return;
}
AbstractFile file = node.getLookup().lookup(AbstractFile.class);
Image image = node.getLookup().lookup(Image.class);
DataSource dataSource = node.getLookup().lookup(DataSource.class);
@ -181,6 +176,7 @@ public class Metadata extends javax.swing.JPanel implements DataContentViewer {
addRow(sb, NbBundle.getMessage(this.getClass(), "Metadata.tableRowTitle.created"), ContentUtils.getStringTime(file.getCrtime(), file));
addRow(sb, NbBundle.getMessage(this.getClass(), "Metadata.tableRowTitle.changed"), ContentUtils.getStringTime(file.getCtime(), file));
String md5 = file.getMd5Hash();
if (md5 == null) {
md5 = NbBundle.getMessage(this.getClass(), "Metadata.tableRowContent.md5notCalc");
@ -217,8 +213,8 @@ public class Metadata extends javax.swing.JPanel implements DataContentViewer {
endTable(sb);
/*
* If we have a file system file, grab the more detailed metadata
* text too
* If we have a file system file, grab the more detailed metadata text
* too
*/
try {
if (file instanceof FsContent) {
@ -231,10 +227,10 @@ public class Metadata extends javax.swing.JPanel implements DataContentViewer {
sb.append(str).append("<br />"); //NON-NLS
/*
* Very long results can cause the UI to hang before
* displaying, so truncate the results if necessary.
* Very long results can cause the UI to hang before displaying,
* so truncate the results if necessary.
*/
if (sb.length() > 50000) {
if(sb.length() > 50000){
sb.append(NbBundle.getMessage(this.getClass(), "Metadata.nodeText.truncated"));
break;
}
@ -286,7 +282,7 @@ public class Metadata extends javax.swing.JPanel implements DataContentViewer {
StringBuilder pathValues = new StringBuilder("<div>");
pathValues.append(imagePaths[0]);
pathValues.append("</div>");
for (int i = 1; i < imagePaths.length; i++) {
for (int i=1; i < imagePaths.length; i++) {
pathValues.append("<div>");
pathValues.append(imagePaths[i]);
pathValues.append("</div>");
@ -304,18 +300,18 @@ public class Metadata extends javax.swing.JPanel implements DataContentViewer {
}
/**
* Adds a row for download source from the given associated artifact, if the
* associated artifacts specifies a source.
* Adds a row for download source from the given associated artifact,
* if the associated artifacts specifies a source.
*
* @param sb string builder.
* @param associatedArtifact
*
* @throws TskCoreException if there is an error
*/
private void addDownloadSourceRow(StringBuilder sb, BlackboardArtifact associatedArtifact) throws TskCoreException {
if (associatedArtifact != null
&& ((associatedArtifact.getArtifactTypeID() == ARTIFACT_TYPE.TSK_WEB_DOWNLOAD.getTypeID())
|| (associatedArtifact.getArtifactTypeID() == ARTIFACT_TYPE.TSK_WEB_CACHE.getTypeID()))) {
private void addDownloadSourceRow(StringBuilder sb, BlackboardArtifact associatedArtifact ) throws TskCoreException {
if (associatedArtifact != null &&
((associatedArtifact.getArtifactTypeID() == ARTIFACT_TYPE.TSK_WEB_DOWNLOAD.getTypeID()) ||
(associatedArtifact.getArtifactTypeID() == ARTIFACT_TYPE.TSK_WEB_CACHE.getTypeID())) ) {
BlackboardAttribute urlAttr = associatedArtifact.getAttribute(new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_URL));
if (urlAttr != null) {
addRow(sb, NbBundle.getMessage(this.getClass(), "Metadata.tableRowTitle.downloadSource"), urlAttr.getValueString());
@ -373,22 +369,6 @@ public class Metadata extends javax.swing.JPanel implements DataContentViewer {
public boolean isSupported(Node node) {
Image image = node.getLookup().lookup(Image.class);
AbstractFile file = node.getLookup().lookup(AbstractFile.class);
if (file != null && node instanceof BlackboardArtifactNode) {
BlackboardArtifact theArtifact = ((BlackboardArtifactNode) node).getArtifact();
//disable the content viewer when a download or cached file does not exist instead of displaying its parent
try {
if ((theArtifact.getArtifactTypeID() == BlackboardArtifact.ARTIFACT_TYPE.TSK_WEB_DOWNLOAD.getTypeID()
|| theArtifact.getArtifactTypeID() == BlackboardArtifact.ARTIFACT_TYPE.TSK_WEB_CACHE.getTypeID())
&& file.getId() == theArtifact.getParent().getId()) {
return false;
}
} catch (TskCoreException ex) {
LOGGER.log(Level.WARNING, String.format("Error getting parent of artifact with type %s and objID = %d can not confirm file with name %s and objId = %d is not the parent. Metadata viewer will not be supported.",
theArtifact.getArtifactTypeName(), theArtifact.getObjectID(), file.getName(), file.getId()), ex);
return false;
}
}
return (file != null) || (image != null);
}

View File

@ -36,7 +36,6 @@ import org.sleuthkit.autopsy.casemodule.Case;
import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException;
import org.sleuthkit.autopsy.corecomponentinterfaces.DataContentViewer;
import org.sleuthkit.autopsy.coreutils.Logger;
import org.sleuthkit.autopsy.datamodel.BlackboardArtifactNode;
import org.sleuthkit.datamodel.AbstractFile;
import org.sleuthkit.datamodel.BlackboardArtifact;
import static org.sleuthkit.datamodel.BlackboardArtifact.ARTIFACT_TYPE.TSK_ASSOCIATED_OBJECT;
@ -226,21 +225,6 @@ public final class ContextViewer extends javax.swing.JPanel implements DataConte
// check if the node has an abstract file and the file has any context defining artifacts.
if (node.getLookup().lookup(AbstractFile.class) != null) {
AbstractFile abstractFile = node.getLookup().lookup(AbstractFile.class);
if (node instanceof BlackboardArtifactNode) {
BlackboardArtifact theArtifact = ((BlackboardArtifactNode) node).getArtifact();
//disable the content viewer when a download or cached file does not exist instead of displaying its parent
try {
if ((theArtifact.getArtifactTypeID() == BlackboardArtifact.ARTIFACT_TYPE.TSK_WEB_DOWNLOAD.getTypeID()
|| theArtifact.getArtifactTypeID() == BlackboardArtifact.ARTIFACT_TYPE.TSK_WEB_CACHE.getTypeID())
&& abstractFile.getId() == theArtifact.getParent().getId()) {
return false;
}
} catch (TskCoreException ex) {
logger.log(Level.WARNING, String.format("Error getting parent of artifact with type %s and objID = %d can not confirm file with name %s and objId = %d is not the parent. Context content viewer will not be supported.",
theArtifact.getArtifactTypeName(), theArtifact.getObjectID(), abstractFile.getName(), abstractFile.getId()), ex);
return false;
}
}
for (BlackboardArtifact.ARTIFACT_TYPE artifactType : CONTEXT_ARTIFACTS) {
List<BlackboardArtifact> artifactsList;
try {
@ -265,7 +249,8 @@ public final class ContextViewer extends javax.swing.JPanel implements DataConte
}
@NbBundle.Messages({
"ContextViewer.unknownSource=Unknown ",})
"ContextViewer.unknownSource=Unknown ",
})
/**
* Looks for context providing artifacts for the given file and populates
* the source context.
@ -317,11 +302,11 @@ public final class ContextViewer extends javax.swing.JPanel implements DataConte
jScrollPane.repaint();
jScrollPane.revalidate();
}
/**
* Resolves an TSK_ASSOCIATED_OBJECT artifact and adds it to the appropriate
* panel
* Resolves an TSK_ASSOCIATED_OBJECT artifact and adds it to the appropriate panel
*
* @param artifact Artifact that may provide context.
*
@ -414,7 +399,8 @@ public final class ContextViewer extends javax.swing.JPanel implements DataConte
}
/**
* Returns a display string with recent Doc artifact.
* Returns a display string with recent Doc
* artifact.
*
* @param artifact artifact to get doc from.
*
@ -443,7 +429,8 @@ public final class ContextViewer extends javax.swing.JPanel implements DataConte
}
/**
* Returns a display string with Program Execution artifact.
* Returns a display string with Program Execution
* artifact.
*
* @param artifact artifact to get doc from.
*
@ -553,7 +540,6 @@ public final class ContextViewer extends javax.swing.JPanel implements DataConte
}
interface DateTimePanel {
/**
* Return the date time value for this panel.
*
@ -593,11 +579,11 @@ public final class ContextViewer extends javax.swing.JPanel implements DataConte
Long dateTime1 = panel1.getDateTime();
Long dateTime2 = panel2.getDateTime();
if (dateTime1 == null && dateTime2 == null) {
if(dateTime1 == null && dateTime2 == null) {
return 0;
} else if (dateTime1 == null) {
} else if(dateTime1 == null) {
return -1;
} else if (dateTime2 == null) {
} else if(dateTime2 == null) {
return 1;
}

View File

@ -19,16 +19,11 @@
package org.sleuthkit.autopsy.contentviewers.textcontentviewer;
import java.awt.Component;
import java.util.logging.Level;
import org.openide.nodes.Node;
import org.openide.util.NbBundle.Messages;
import org.openide.util.lookup.ServiceProvider;
import org.sleuthkit.autopsy.corecomponentinterfaces.DataContentViewer;
import org.sleuthkit.autopsy.coreutils.Logger;
import org.sleuthkit.autopsy.datamodel.BlackboardArtifactNode;
import org.sleuthkit.datamodel.AbstractFile;
import org.sleuthkit.datamodel.BlackboardArtifact;
import org.sleuthkit.datamodel.TskCoreException;
/**
* A DataContentViewer that displays text with the TextViewers available.
@ -38,7 +33,6 @@ public class TextContentViewer implements DataContentViewer {
private final TextContentViewerPanel panel;
private volatile Node currentNode = null;
private static final Logger logger = Logger.getLogger(TextContentViewer.class.getName());
/**
* No arg constructor for creating the main instance of this Content Viewer.
@ -58,10 +52,6 @@ public class TextContentViewer implements DataContentViewer {
@Override
public void setNode(Node selectedNode) {
if ((selectedNode == null) || (!isSupported(selectedNode))) {
resetComponent();
return;
}
currentNode = selectedNode;
panel.setNode(currentNode);
@ -106,21 +96,7 @@ public class TextContentViewer implements DataContentViewer {
if (file == null) {
return false;
}
if (node instanceof BlackboardArtifactNode) {
BlackboardArtifact theArtifact = ((BlackboardArtifactNode) node).getArtifact();
//disable the content viewer when a download or cached file does not exist instead of displaying its parent
try {
if ((theArtifact.getArtifactTypeID() == BlackboardArtifact.ARTIFACT_TYPE.TSK_WEB_DOWNLOAD.getTypeID()
|| theArtifact.getArtifactTypeID() == BlackboardArtifact.ARTIFACT_TYPE.TSK_WEB_CACHE.getTypeID())
&& file.getId() == theArtifact.getParent().getId()) {
return false;
}
} catch (TskCoreException ex) {
logger.log(Level.WARNING, String.format("Error getting parent of artifact with type %s and objID = %d can not confirm file with name %s and objId = %d is not the parent. Text content viewer will not be supported.",
theArtifact.getArtifactTypeName(), theArtifact.getObjectID(), file.getName(), file.getId()), ex);
return false;
}
}
// disable the text content viewer for directories and empty files
if (file.isDir() || file.getSize() == 0) {
return false;

View File

@ -501,41 +501,26 @@ public class DataContentViewerArtifact extends javax.swing.JPanel implements Dat
Lookup lookup = selectedNode.getLookup();
// Get the content. We may get BlackboardArtifacts, ignore those here.
ArrayList<BlackboardArtifact> artifacts = new ArrayList<>();
Collection<? extends Content> contents = lookup.lookupAll(Content.class);
if (contents.isEmpty()) {
return new ViewUpdate(getArtifactContents().size(), currentPage, ERROR_TEXT);
}
Content underlyingContent = null;
//find the first non-artifact content from the lookup results
for (Content content : contents) {
if ((content != null) && (!(content instanceof BlackboardArtifact))) {
underlyingContent = content;
break;
}
}
ArrayList<BlackboardArtifact> contentArtifacts = new ArrayList<>();
if (underlyingContent != null) {
try {
//get the artifacts seperately for the use case where an artifact is about a file that exists other than its parent such as a TSK_WEB_DOWNLOAD or TSK_WEB_CACHE
Collection<? extends BlackboardArtifact> nodeArtifacts = lookup.lookupAll(BlackboardArtifact.class);
if (!nodeArtifacts.isEmpty()) {
BlackboardArtifact originalArtifact = nodeArtifacts.iterator().next();
if ((originalArtifact.getArtifactTypeID() == BlackboardArtifact.ARTIFACT_TYPE.TSK_WEB_DOWNLOAD.getTypeID()
|| originalArtifact.getArtifactTypeID() == BlackboardArtifact.ARTIFACT_TYPE.TSK_WEB_CACHE.getTypeID())
&& underlyingContent.getId() == originalArtifact.getParent().getId()) {
contentArtifacts.add(originalArtifact);
}
}
if (contentArtifacts.isEmpty()) {
// Get all of the blackboard artifacts associated with the content. These are what this
// viewer displays.
contentArtifacts = underlyingContent.getAllArtifacts();
}
try {
artifacts = content.getAllArtifacts();
underlyingContent = content;
break;
} catch (TskException ex) {
logger.log(Level.SEVERE, "Couldn't get artifacts", ex); //NON-NLS
return new ViewUpdate(getArtifactContents().size(), currentPage, ERROR_TEXT);
}
}
}
if (isCancelled()) {
return null;
@ -543,7 +528,7 @@ public class DataContentViewerArtifact extends javax.swing.JPanel implements Dat
// Build the new artifact contents cache.
ArrayList<BlackboardArtifact> artifactContents = new ArrayList<>();
for (BlackboardArtifact artifact : contentArtifacts) {
for (BlackboardArtifact artifact : artifacts) {
artifactContents.add(artifact);
}
@ -552,7 +537,7 @@ public class DataContentViewerArtifact extends javax.swing.JPanel implements Dat
int index = 0;
BlackboardArtifact artifact = lookup.lookup(BlackboardArtifact.class);
if (artifact != null) {
index = contentArtifacts.indexOf(artifact);
index = artifacts.indexOf(artifact);
if (index == -1) {
index = 0;
} else {
@ -562,9 +547,9 @@ public class DataContentViewerArtifact extends javax.swing.JPanel implements Dat
if (attr.getAttributeType().getTypeID() == BlackboardAttribute.ATTRIBUTE_TYPE.TSK_ASSOCIATED_ARTIFACT.getTypeID()) {
long assocArtifactId = attr.getValueLong();
int assocArtifactIndex = -1;
for (BlackboardArtifact art : contentArtifacts) {
for (BlackboardArtifact art : artifacts) {
if (assocArtifactId == art.getArtifactID()) {
assocArtifactIndex = contentArtifacts.indexOf(art);
assocArtifactIndex = artifacts.indexOf(art);
break;
}
}

View File

@ -44,10 +44,8 @@ import org.sleuthkit.autopsy.core.UserPreferences;
import org.sleuthkit.autopsy.corecomponentinterfaces.DataContentViewer;
import static org.sleuthkit.autopsy.corecomponents.Bundle.*;
import org.sleuthkit.autopsy.coreutils.FileUtil;
import org.sleuthkit.autopsy.datamodel.BlackboardArtifactNode;
import org.sleuthkit.autopsy.datamodel.ContentUtils;
import org.sleuthkit.autopsy.datamodel.DataConversion;
import org.sleuthkit.datamodel.BlackboardArtifact;
import org.sleuthkit.datamodel.Content;
import org.sleuthkit.datamodel.TskCoreException;
@ -608,24 +606,7 @@ public class DataContentViewerHex extends javax.swing.JPanel implements DataCont
return false;
}
Content content = DataContentViewerUtility.getDefaultContent(node);
if (content == null || content.getSize() <= 0) {
return false;
} else if (node instanceof BlackboardArtifactNode) {
BlackboardArtifact theArtifact = ((BlackboardArtifactNode) node).getArtifact();
//disable the content viewer when a download or cached file does not exist instead of displaying its parent
try {
if ((theArtifact.getArtifactTypeID() == BlackboardArtifact.ARTIFACT_TYPE.TSK_WEB_DOWNLOAD.getTypeID()
|| theArtifact.getArtifactTypeID() == BlackboardArtifact.ARTIFACT_TYPE.TSK_WEB_CACHE.getTypeID())
&& content.getId() == theArtifact.getParent().getId()) {
return false;
}
} catch (TskCoreException ex) {
logger.log(Level.WARNING, String.format("Error getting parent of artifact with type %s and objID = %d can not confirm content with name %s and objId = %d is not the parent. Hex content viewer will not be supported.",
theArtifact.getArtifactTypeName(), theArtifact.getObjectID(), content.getName(), content.getId()), ex);
return false;
}
}
return true;
return content != null && content.getSize() > 0;
}
@Override

View File

@ -1,3 +1,7 @@
# {0} - month abbreviation
# {1} - day of month
# {2} - year
DiscoveryAttributes.ActivityDateGroupKey.getDisplayNameTemplate=Week of {0} {1}, {2}
DiscoveryAttributes.GroupingAttributeType.datasource.displayName=Data Source
DiscoveryAttributes.GroupingAttributeType.fileType.displayName=File Type
DiscoveryAttributes.GroupingAttributeType.firstDate.displayName=First Activity Date
@ -20,16 +24,11 @@ DiscoveryKeyUtils.DataSourceGroupKey.datasourceAndID={0}(ID: {1})
# {0} - Data source ID
DiscoveryKeyUtils.DataSourceGroupKey.idOnly=Data source (ID: {0})
DiscoveryKeyUtils.FileTagGroupKey.noSets=None
DiscoveryKeyUtils.FirstActivityDateGroupKey.noDate=No Date Available
DiscoveryKeyUtils.HashHitsGroupKey.noHashHits=None
DiscoveryKeyUtils.InterestingItemGroupKey.noSets=None
DiscoveryKeyUtils.KeywordListGroupKey.noKeywords=None
DiscoveryKeyUtils.LastActivityDateGroupKey.noDate=No Date Available
DiscoveryKeyUtils.NoGroupingGroupKey.allFiles=All Files
DiscoveryKeyUtils.ObjectDetectedGroupKey.noSets=None
# {0} - totalVisits
DiscoveryKeyUtils.PageViewsGroupKey.displayName={0} page views
DiscoveryKeyUtils.PageViewsGroupKey.noVisits=No page views
# {0} - domain
# {1} - artifactType
DomainSearchArtifactsRequest.toString.text=Domain: {0} ArtifactType: {1}
@ -94,6 +93,10 @@ SearchData.Frequency.unique.displayName=Unique (1)
SearchData.Frequency.unknown.displayName=Unknown
SearchData.Frequency.verycommon.displayName=Very Common (100+)
SearchData.notPrevNotable.displayName=Previously Not Notable
SearchData.PageViews.over1000=1000+ page views
# {0} - minValue
# {1} - maxValue
SearchData.PageViews.rangeTemplate={0}-{1} page views
SearchData.prevNotable.displayName=Previously Notable
SearchData.Score.interesting.displayName=Interesting
SearchData.Score.notable.displayName=Notable

View File

@ -986,9 +986,9 @@ public class DiscoveryAttributes {
*/
public static List<GroupingAttributeType> getOptionsForGroupingForDomains() {
if (CentralRepository.isEnabled()) {
return Arrays.asList(FREQUENCY, LAST_ACTIVITY_DATE, FIRST_ACTIVITY_DATE, PAGE_VIEWS, PREVIOUSLY_NOTABLE, DOMAIN_CATEGORY);
return Arrays.asList(PAGE_VIEWS, FREQUENCY, LAST_ACTIVITY_DATE, FIRST_ACTIVITY_DATE, PREVIOUSLY_NOTABLE, DOMAIN_CATEGORY);
} else {
return Arrays.asList(LAST_ACTIVITY_DATE, FIRST_ACTIVITY_DATE, PAGE_VIEWS, DOMAIN_CATEGORY);
return Arrays.asList(PAGE_VIEWS, LAST_ACTIVITY_DATE, FIRST_ACTIVITY_DATE, DOMAIN_CATEGORY);
}
}
}

View File

@ -18,17 +18,21 @@
*/
package org.sleuthkit.autopsy.discovery.search;
import java.text.SimpleDateFormat;
import java.time.DayOfWeek;
import java.time.Instant;
import java.time.ZonedDateTime;
import java.time.temporal.TemporalAdjusters;
import java.util.Collections;
import java.util.Date;
import java.util.List;
import java.util.Locale;
import java.util.Objects;
import java.util.concurrent.TimeUnit;
import java.util.TimeZone;
import java.util.logging.Level;
import org.openide.util.NbBundle;
import org.sleuthkit.autopsy.centralrepository.datamodel.CentralRepository;
import org.sleuthkit.autopsy.coreutils.Logger;
import org.sleuthkit.autopsy.datamodel.ContentUtils;
import org.sleuthkit.autopsy.discovery.search.SearchData.PageViews;
import org.sleuthkit.autopsy.discovery.ui.MonthAbbreviation;
import org.sleuthkit.datamodel.AbstractFile;
import org.sleuthkit.datamodel.Content;
import org.sleuthkit.datamodel.SleuthkitCase;
@ -1133,29 +1137,34 @@ public class DiscoveryKeyUtils {
*/
static class LastActivityDateGroupKey extends GroupKey {
private final Long epochDate;
private final String dateNameString;
private ZonedDateTime currentWeekCutOff;
/**
* Construct a new LastActivityDateGroupKey.
*
* @param result The Result to create the group key for.
*/
@NbBundle.Messages({
"DiscoveryKeyUtils.LastActivityDateGroupKey.noDate=No Date Available"})
LastActivityDateGroupKey(Result result) {
if (result instanceof ResultDomain) {
epochDate = ((ResultDomain) result).getActivityEnd();
dateNameString = new SimpleDateFormat("yyyy/MM/dd", Locale.getDefault()).format(new Date(TimeUnit.SECONDS.toMillis(epochDate)));
ResultDomain domainResult = ((ResultDomain) result);
currentWeekCutOff = getCurrentWeekCutOff(domainResult.getActivityEnd(), domainResult);
} else {
epochDate = Long.MAX_VALUE;
dateNameString = Bundle.DiscoveryKeyUtils_LastActivityDateGroupKey_noDate();
throw new IllegalArgumentException("Expected a domain result only.");
}
}
@NbBundle.Messages({
"# {0} - month abbreviation",
"# {1} - day of month",
"# {2} - year",
"DiscoveryAttributes.ActivityDateGroupKey.getDisplayNameTemplate=Week of {0} {1}, {2}"
})
@Override
String getDisplayName() {
return getDateNameString();
MonthAbbreviation currentCutOffMonth = MonthAbbreviation.fromMonthValue(currentWeekCutOff.getMonthValue());
return Bundle.DiscoveryAttributes_ActivityDateGroupKey_getDisplayNameTemplate(
currentCutOffMonth.toString(), Integer.toString(currentWeekCutOff.getDayOfMonth()),
Integer.toString(currentWeekCutOff.getYear()));
}
@Override
@ -1169,53 +1178,40 @@ public class DiscoveryKeyUtils {
}
LastActivityDateGroupKey dateGroupKey = (LastActivityDateGroupKey) otherKey;
return getDateNameString().equals(dateGroupKey.getDateNameString());
return getDisplayName().equals(dateGroupKey.getDisplayName());
}
@Override
public int hashCode() {
return Objects.hash(getDateNameString());
return Objects.hash(getDisplayName());
}
@Override
public int compareTo(GroupKey otherGroupKey) {
if (otherGroupKey instanceof LastActivityDateGroupKey) {
LastActivityDateGroupKey otherDateGroupKey = (LastActivityDateGroupKey) otherGroupKey;
// Put the empty list at the end
if (this.getEpochDate().equals(Long.MAX_VALUE)) {
if (otherDateGroupKey.getEpochDate().equals(Long.MAX_VALUE)) {
return 0;
} else {
return 1;
}
} else if (otherDateGroupKey.getEpochDate().equals(Long.MAX_VALUE)) {
return -1;
}
return getDateNameString().compareTo(otherDateGroupKey.getDateNameString());
return Long.compare(otherDateGroupKey.currentWeekCutOff.toEpochSecond(), currentWeekCutOff.toEpochSecond());
} else {
return compareClassNames(otherGroupKey);
}
}
/**
* Get the date this group is for as a Long.
*
* @return The date.
*/
Long getEpochDate() {
return epochDate;
}
/**
* Get the name which identifies this group.
*
* @return The dateNameString.
* Get the next closed Sunday given an epoch time and timezone.
* Dates for grouping are managed on a weekly basis. Each Sunday
* acts as the boundary and representative for the week.
*/
String getDateNameString() {
return dateNameString;
}
private static ZonedDateTime getCurrentWeekCutOff(long epochSeconds, ResultDomain domainResult) {
Instant startActivityAsInsant = Instant.ofEpochSecond(epochSeconds);
// Determines the timezone using the settings panel or value parsed from the
// parent data source
TimeZone currentTimeZone = ContentUtils.getTimeZone(domainResult.getDataSource());
// Convert to a datetime using epoch and timezone.
ZonedDateTime startActivityAsDateTime = ZonedDateTime.ofInstant(startActivityAsInsant, currentTimeZone.toZoneId());
// Get the closest Sunday, which is the cut off for the current week.
// Use this cut off to perform grouping and comparing.
return startActivityAsDateTime.with(TemporalAdjusters.nextOrSame(DayOfWeek.SUNDAY));
}
/**
@ -1223,29 +1219,28 @@ public class DiscoveryKeyUtils {
*/
static class FirstActivityDateGroupKey extends GroupKey {
private final Long epochDate;
private final String dateNameString;
private ZonedDateTime currentWeekCutOff;
/**
* Construct a new FirstActivityDateGroupKey.
*
* @param result The Result to create the group key for.
*/
@NbBundle.Messages({
"DiscoveryKeyUtils.FirstActivityDateGroupKey.noDate=No Date Available"})
FirstActivityDateGroupKey(Result result) {
if (result instanceof ResultDomain) {
epochDate = ((ResultDomain) result).getActivityStart();
dateNameString = new SimpleDateFormat("yyyy/MM/dd", Locale.getDefault()).format(new Date(TimeUnit.SECONDS.toMillis(epochDate)));
ResultDomain domainResult = ((ResultDomain) result);
currentWeekCutOff = getCurrentWeekCutOff(domainResult.getActivityStart(), domainResult);
} else {
epochDate = Long.MAX_VALUE;
dateNameString = Bundle.DiscoveryKeyUtils_FirstActivityDateGroupKey_noDate();
throw new IllegalArgumentException("Expected a domain result only.");
}
}
@Override
String getDisplayName() {
return getDateNameString();
MonthAbbreviation currentCutOffMonth = MonthAbbreviation.fromMonthValue(currentWeekCutOff.getMonthValue());
return Bundle.DiscoveryAttributes_ActivityDateGroupKey_getDisplayNameTemplate(
currentCutOffMonth.toString(), Integer.toString(currentWeekCutOff.getDayOfMonth()),
Integer.toString(currentWeekCutOff.getYear()));
}
@Override
@ -1259,53 +1254,23 @@ public class DiscoveryKeyUtils {
}
FirstActivityDateGroupKey dateGroupKey = (FirstActivityDateGroupKey) otherKey;
return getDateNameString().equals(dateGroupKey.getDateNameString());
return getDisplayName().equals(dateGroupKey.getDisplayName());
}
@Override
public int hashCode() {
return Objects.hash(getDateNameString());
return Objects.hash(getDisplayName());
}
@Override
public int compareTo(GroupKey otherGroupKey) {
if (otherGroupKey instanceof FirstActivityDateGroupKey) {
FirstActivityDateGroupKey otherDateGroupKey = (FirstActivityDateGroupKey) otherGroupKey;
// Put the empty list at the end
if (this.getEpochDate().equals(Long.MAX_VALUE)) {
if (otherDateGroupKey.getEpochDate().equals(Long.MAX_VALUE)) {
return 0;
} else {
return 1;
}
} else if (otherDateGroupKey.getEpochDate().equals(Long.MAX_VALUE)) {
return -1;
}
return getDateNameString().compareTo(otherDateGroupKey.getDateNameString());
return Long.compare(otherDateGroupKey.currentWeekCutOff.toEpochSecond(), currentWeekCutOff.toEpochSecond());
} else {
return compareClassNames(otherGroupKey);
}
}
/**
* Get the date this group is for as a Long.
*
* @return The date.
*/
Long getEpochDate() {
return epochDate;
}
/**
* Get the name which identifies this group.
*
* @return The dateNameString.
*/
String getDateNameString() {
return dateNameString;
}
}
/**
@ -1316,28 +1281,23 @@ public class DiscoveryKeyUtils {
static class PageViewsGroupKey extends GroupKey {
private final String displayName;
private final Long pageViews;
private final PageViews pageViews;
/**
* Construct a new NumberOfVisitsGroupKey.
*
* @param result The Result to create the group key for.
*/
@NbBundle.Messages({
"# {0} - totalVisits",
"DiscoveryKeyUtils.PageViewsGroupKey.displayName={0} page views",
"DiscoveryKeyUtils.PageViewsGroupKey.noVisits=No page views"})
PageViewsGroupKey(Result result) {
if (result instanceof ResultDomain) {
Long totalPageViews = ((ResultDomain) result).getTotalPageViews();
if (totalPageViews == null) {
totalPageViews = 0L;
}
pageViews = totalPageViews;
displayName = Bundle.DiscoveryKeyUtils_PageViewsGroupKey_displayName(Long.toString(pageViews));
pageViews = PageViews.fromPageViewCount(totalPageViews);
displayName = pageViews.toString();
} else {
displayName = Bundle.DiscoveryKeyUtils_PageViewsGroupKey_noVisits();
pageViews = -1L;
throw new IllegalArgumentException("Expected a domain instance only.");
}
}
@ -1356,7 +1316,7 @@ public class DiscoveryKeyUtils {
*
* @return The number of page views this group is for.
*/
Long getPageViews() {
PageViews getPageViews() {
return pageViews;
}
@ -1378,7 +1338,7 @@ public class DiscoveryKeyUtils {
public int compareTo(GroupKey otherGroupKey) {
if (otherGroupKey instanceof PageViewsGroupKey) {
PageViewsGroupKey pageViewsKey = (PageViewsGroupKey) otherGroupKey;
return Long.compare(getPageViews(), pageViewsKey.getPageViews());
return getPageViews().compareTo(pageViewsKey.getPageViews());
} else {
return compareClassNames(otherGroupKey);
}

View File

@ -24,12 +24,15 @@ import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.TimeZone;
import org.apache.commons.lang3.StringUtils;
import org.sleuthkit.autopsy.centralrepository.datamodel.CentralRepository;
import org.sleuthkit.autopsy.datamodel.ContentUtils;
import org.sleuthkit.autopsy.discovery.search.DiscoveryKeyUtils.GroupKey;
import org.sleuthkit.datamodel.BlackboardArtifact;
import org.sleuthkit.datamodel.BlackboardAttribute;
import org.sleuthkit.datamodel.SleuthkitCase;
import org.sleuthkit.datamodel.TimeUtilities;
import org.sleuthkit.datamodel.TskCoreException;
/**
@ -245,7 +248,8 @@ public class DomainSearch {
private String getDate(BlackboardArtifact artifact) throws TskCoreException {
for (BlackboardAttribute attribute : artifact.getAttributes()) {
if (attribute.getAttributeType().getTypeName().startsWith("TSK_DATETIME")) {
String dateString = attribute.getDisplayString();
TimeZone timeZone = ContentUtils.getTimeZone(artifact);
String dateString = TimeUtilities.epochToTime(attribute.getValueLong(), timeZone);
if (dateString.length() >= 10) {
return dateString.substring(0, 10);
}

View File

@ -212,13 +212,14 @@ class DomainSearchCacheLoader extends CacheLoader<SearchKey, Map<GroupKey, List<
final StringJoiner whereClause = new StringJoiner(" OR ");
final StringJoiner havingClause = new StringJoiner(" AND ");
String artifactTypeFilter = null;
// Capture all types by default.
ArtifactTypeFilter artifactTypeFilter = new ArtifactTypeFilter(SearchData.Type.DOMAIN.getArtifactTypes());
boolean hasDateTimeFilter = false;
for (AbstractFilter filter : filters) {
if (filter instanceof ArtifactTypeFilter) {
artifactTypeFilter = ((ArtifactTypeFilter) filter)
.getWhereClause(Arrays.asList(TSK_WEB_ACCOUNT_TYPE));
// Replace with user defined types.
artifactTypeFilter = ((ArtifactTypeFilter) filter);
} else if (!(filter instanceof DataSourceFilter) && !filter.useAlternateFilter()) {
if (filter instanceof ArtifactDateRangeFilter) {
hasDateTimeFilter = true;
@ -240,7 +241,7 @@ class DomainSearchCacheLoader extends CacheLoader<SearchKey, Map<GroupKey, List<
havingClause.add("SUM(CASE WHEN " + domainAttributeFilter + " THEN 1 ELSE 0 END) > 0");
return Pair.of(
whereClause.toString() + ((artifactTypeFilter != null) ? " AND (" + artifactTypeFilter + ")" : ""),
whereClause.toString() + " AND (" + artifactTypeFilter.getWhereClause(Arrays.asList(TSK_WEB_ACCOUNT_TYPE)) + ")",
havingClause.toString()
);
}

View File

@ -151,7 +151,7 @@ public class ResultDomain extends Result {
}
@Override
public Content getDataSource() throws TskCoreException {
public Content getDataSource() {
return this.dataSource;
}

View File

@ -36,7 +36,13 @@ import org.sleuthkit.datamodel.BlackboardArtifact;
public final class SearchData {
private final static long BYTES_PER_MB = 1000000;
private static final Set<BlackboardArtifact.ARTIFACT_TYPE> DOMAIN_ARTIFACT_TYPES = EnumSet.of(BlackboardArtifact.ARTIFACT_TYPE.TSK_WEB_BOOKMARK, BlackboardArtifact.ARTIFACT_TYPE.TSK_WEB_CACHE, BlackboardArtifact.ARTIFACT_TYPE.TSK_WEB_COOKIE, BlackboardArtifact.ARTIFACT_TYPE.TSK_WEB_DOWNLOAD, BlackboardArtifact.ARTIFACT_TYPE.TSK_WEB_HISTORY, BlackboardArtifact.ARTIFACT_TYPE.TSK_WEB_SEARCH_QUERY);
private static final Set<BlackboardArtifact.ARTIFACT_TYPE> DOMAIN_ARTIFACT_TYPES =
EnumSet.of(BlackboardArtifact.ARTIFACT_TYPE.TSK_WEB_BOOKMARK,
BlackboardArtifact.ARTIFACT_TYPE.TSK_WEB_CACHE,
BlackboardArtifact.ARTIFACT_TYPE.TSK_WEB_COOKIE,
BlackboardArtifact.ARTIFACT_TYPE.TSK_WEB_DOWNLOAD,
BlackboardArtifact.ARTIFACT_TYPE.TSK_WEB_HISTORY,
BlackboardArtifact.ARTIFACT_TYPE.TSK_WEB_SEARCH_QUERY);
/**
@ -67,6 +73,62 @@ public final class SearchData {
return displayName;
}
}
/**
* Enum representing the number of page views a domain has received. Page
* views a grouped into ranges for cleaner display and management.
*/
@NbBundle.Messages({
"# {0} - minValue",
"# {1} - maxValue",
"SearchData.PageViews.rangeTemplate={0}-{1} page views",
"SearchData.PageViews.over1000=1000+ page views"
})
public enum PageViews {
OVER_1000(1001, Long.MAX_VALUE), // ranking, minValue, maxValue
UP_TO_1000(501, 1000),
UP_TO_500(101, 500),
UP_TO_100(51, 100),
UP_TO_50(11, 50),
UP_TO_10(0, 10);
private final long minValue;
private final long maxValue;
PageViews(long minValue, long maxValue) {
this.maxValue = maxValue;
this.minValue = minValue;
}
@Override
public String toString() {
if (this == PageViews.OVER_1000) {
return Bundle.SearchData_PageViews_over1000();
} else {
return Bundle.SearchData_PageViews_rangeTemplate(Long.toString(minValue), Long.toString(maxValue));
}
}
/**
* Determines if the given count is covered by this PageView interval.
*/
boolean covers(long count) {
return count >= minValue && count <= maxValue;
}
/**
* Utility to fetch the appropriate PageView interval for the given count.
*/
public static PageViews fromPageViewCount(long count) {
for (PageViews view : PageViews.values()) {
if (view.covers(count)) {
return view;
}
}
return null;
}
}
/**
* Enum representing how often the result occurs in the Central Repository.
*/

View File

@ -33,6 +33,7 @@ import org.sleuthkit.datamodel.TagName;
import org.sleuthkit.datamodel.TskCoreException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.Date;
import java.util.List;
@ -206,7 +207,7 @@ public class SearchFiltering {
*/
public static class ArtifactTypeFilter extends AbstractFilter {
private final List<ARTIFACT_TYPE> types;
private final Collection<ARTIFACT_TYPE> types;
/**
* Construct a new ArtifactTypeFilter.
@ -214,7 +215,7 @@ public class SearchFiltering {
* @param types The list of BlackboardArtifact types to include in
* results from.
*/
public ArtifactTypeFilter(List<ARTIFACT_TYPE> types) {
public ArtifactTypeFilter(Collection<ARTIFACT_TYPE> types) {
this.types = types;
}
@ -223,8 +224,8 @@ public class SearchFiltering {
*
* @return The list of artifact types specified by the filter.
*/
public List<ARTIFACT_TYPE> getTypes() {
return Collections.unmodifiableList(types);
public Collection<ARTIFACT_TYPE> getTypes() {
return Collections.unmodifiableCollection(types);
}
private StringJoiner joinStandardArtifactTypes() {

View File

@ -77,7 +77,22 @@ MiniTimelineArtifactListPanel.value.noValue=No value available.
MiniTimelineDateListPanel.countColumn.name=Count
MiniTimelineDateListPanel.dateColumn.name=Date
MiniTimelineDateListPanel.value.noValue=No value available.
<<<<<<< HEAD
MiniTimelinePanel.loadingPanel.details=the Mini Timeline view
=======
MonthAbbreviation.aprilAbbrev=Apr
MonthAbbreviation.augustAbbrev=Aug
MonthAbbreviation.decemberAbbrev=Dec
MonthAbbreviation.feburaryAbbrev=Feb
MonthAbbreviation.januraryAbbrev=Jan
MonthAbbreviation.julyAbbrev=Jul
MonthAbbreviation.juneAbbrev=Jun
MonthAbbreviation.marchAbbrev=Mar
MonthAbbreviation.mayAbbrev=May
MonthAbbreviation.novemberAbbrev=Nov
MonthAbbreviation.octoberAbbrev=Oct
MonthAbbreviation.septemberAbbrev=Sep
>>>>>>> 1dd895dc72ac6e7c796a9883a2c790b46c27c47c
ObjectDetectedFilterPanel.error.text=At least one object type name must be selected.
ParentFolderFilterPanel.error.text=At least one parent path must be entered.
PastOccurrencesFilterPanel.error.text=At least one value in the past occurrence filter must be selected.

View File

@ -22,15 +22,16 @@ import java.awt.Color;
import java.awt.Component;
import java.awt.Point;
import java.awt.event.MouseEvent;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Locale;
import java.time.Instant;
import java.time.ZonedDateTime;
import java.util.TimeZone;
import javax.swing.ImageIcon;
import javax.swing.JComponent;
import javax.swing.JList;
import javax.swing.ListCellRenderer;
import org.openide.util.NbBundle;
import org.sleuthkit.autopsy.coreutils.ThreadConfined;
import org.sleuthkit.autopsy.datamodel.ContentUtils;
/**
* Class which displays a preview and details about a domain.
@ -39,7 +40,6 @@ class DomainSummaryPanel extends javax.swing.JPanel implements ListCellRenderer<
private static final long serialVersionUID = 1L;
private static final Color SELECTION_COLOR = new Color(0, 120, 215);
private static final SimpleDateFormat dateFormat = new SimpleDateFormat("MMM dd yyyy", Locale.getDefault());
/**
* Creates new form DomainPanel.
@ -149,8 +149,9 @@ class DomainSummaryPanel extends javax.swing.JPanel implements ListCellRenderer<
@Override
public Component getListCellRendererComponent(JList<? extends DomainWrapper> list, DomainWrapper value, int index, boolean isSelected, boolean cellHasFocus) {
domainNameLabel.setText(value.getResultDomain().getDomain());
String startDate = dateFormat.format(new Date(value.getResultDomain().getActivityStart() * 1000));
String endDate = dateFormat.format(new Date(value.getResultDomain().getActivityEnd() * 1000));
TimeZone timeZone = ContentUtils.getTimeZone(value.getResultDomain().getDataSource());
String startDate = formatDate(value.getResultDomain().getActivityStart(), timeZone);
String endDate = formatDate(value.getResultDomain().getActivityEnd(), timeZone);
activityLabel.setText(Bundle.DomainSummaryPanel_activity_text(startDate, endDate));
totalVisitsLabel.setText(Bundle.DomainSummaryPanel_totalPages_text() + value.getResultDomain().getTotalPageViews());
pagesLabel.setText(Bundle.DomainSummaryPanel_pages_text() + value.getResultDomain().getPageViewsInLast60Days());
@ -166,6 +167,22 @@ class DomainSummaryPanel extends javax.swing.JPanel implements ListCellRenderer<
return this;
}
/**
* Formats an epoch time in a given time zone using the following pattern
*
* MMM dd YYYY
*
* The pattern below is formatted manually to reuse the MonthAbbreviation utility.
*/
private String formatDate(long epochSeconds, TimeZone timeZone) {
Instant epochSecondsAsInstant = Instant.ofEpochSecond(epochSeconds);
ZonedDateTime dateTime = ZonedDateTime.ofInstant(epochSecondsAsInstant, timeZone.toZoneId());
MonthAbbreviation currentCutOffMonth = MonthAbbreviation.fromMonthValue(dateTime.getMonthValue());
return String.format("%s %02d %04d",
currentCutOffMonth.toString(),
dateTime.getDayOfMonth(), dateTime.getYear());
}
@ThreadConfined(type = ThreadConfined.ThreadType.AWT)
@Override
public String getToolTipText(MouseEvent event) {

View File

@ -0,0 +1,80 @@
/*
* Autopsy
*
* Copyright 2020 Basis Technology Corp.
* Contact: carrier <at> sleuthkit <dot> org
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.sleuthkit.autopsy.discovery.ui;
import org.openide.util.NbBundle;
/**
* Utility for representing month abbreviations
*/
@NbBundle.Messages({
"MonthAbbreviation.januraryAbbrev=Jan",
"MonthAbbreviation.feburaryAbbrev=Feb",
"MonthAbbreviation.marchAbbrev=Mar",
"MonthAbbreviation.aprilAbbrev=Apr",
"MonthAbbreviation.mayAbbrev=May",
"MonthAbbreviation.juneAbbrev=Jun",
"MonthAbbreviation.julyAbbrev=Jul",
"MonthAbbreviation.augustAbbrev=Aug",
"MonthAbbreviation.septemberAbbrev=Sep",
"MonthAbbreviation.octoberAbbrev=Oct",
"MonthAbbreviation.novemberAbbrev=Nov",
"MonthAbbreviation.decemberAbbrev=Dec"
})
public enum MonthAbbreviation {
JANURARY(Bundle.MonthAbbreviation_januraryAbbrev()),
FEBURARY(Bundle.MonthAbbreviation_feburaryAbbrev()),
MARCH(Bundle.MonthAbbreviation_marchAbbrev()),
APRIL(Bundle.MonthAbbreviation_aprilAbbrev()),
MAY(Bundle.MonthAbbreviation_mayAbbrev()),
JUNE(Bundle.MonthAbbreviation_juneAbbrev()),
JULY(Bundle.MonthAbbreviation_julyAbbrev()),
AUGUST(Bundle.MonthAbbreviation_augustAbbrev()),
SEPTEMBER(Bundle.MonthAbbreviation_septemberAbbrev()),
OCTOBER(Bundle.MonthAbbreviation_octoberAbbrev()),
NOVEMBER(Bundle.MonthAbbreviation_novemberAbbrev()),
DECEMBER(Bundle.MonthAbbreviation_decemberAbbrev());
private final String abbreviation;
MonthAbbreviation(String abbreviation) {
this.abbreviation = abbreviation;
}
@Override
public String toString() {
return this.abbreviation;
}
/**
* Converts a month value (1-12) to the appropriate abbreviation.
*
* @param value Month value (1-12).
* @return Abbreviation matching the month value, null if not found.
*/
public static MonthAbbreviation fromMonthValue(int value) {
MonthAbbreviation[] months = MonthAbbreviation.values();
for(int i = 0; i < months.length; i++) {
if (i + 1 == value) {
return months[i];
}
}
return null;
}
}

View File

@ -210,7 +210,6 @@ KeywordSearchJobSettingsPanel.languagesLabel.text=Scripts enabled for string ext
KeywordSearchGlobalLanguageSettingsPanel.enableUTF8Checkbox.text=Enable UTF8 text extraction
KeywordSearchGlobalLanguageSettingsPanel.ingestSettingsLabel.text=Ingest settings for string extraction from unknown file types (changes effective on next ingest):
KeywordSearchGlobalLanguageSettingsPanel.enableUTF16Checkbox.text=Enable UTF16LE and UTF16BE string extraction
KeywordSearchGlobalLanguageSettingsPanel.enableOcrCheckbox.text=Enable Optical Character Recognition (OCR)
KeywordSearchGlobalLanguageSettingsPanel.languagesLabel.text=Enabled scripts (languages):
KeywordSearchGlobalSearchSettingsPanel.timeRadioButton1.toolTipText=20 mins. (fastest ingest time)
KeywordSearchGlobalSearchSettingsPanel.timeRadioButton1.text=20 minutes (slowest feedback, fastest ingest)
@ -320,3 +319,4 @@ ExtractedContentPanel.pageTotalLabel.text=-
ExtractedContentPanel.pageOfLabel.text=of
ExtractedContentPanel.pageCurLabel.text=-
ExtractedContentPanel.pagesLabel.text=Page:
KeywordSearchGlobalSearchSettingsPanel.ocrCheckBox.text=Enable Optical Character Recognition (OCR)

View File

@ -18,6 +18,8 @@ GlobalEditListPanel.warning.title=Warning
IndexedText.errorMessage.errorGettingText=<span style='font-style:italic'>Error retrieving indexed text.</span>
IndexedText.warningMessage.knownFile=<span style='font-style:italic'>This file is a known file (based on MD5 hash) and does not have indexed text.</span>
IndexedText.warningMessage.noTextAvailable=<span style='font-style:italic'>No indexed text for this file.</span>
KeywordSearchGlobalLanguageSettingsPanel.enableOcrCheckbox.text=Enable Optical Character Recognition (OCR)
KeywordSearchGlobalSearchSettingsPanel.customizeComponents.windowsOCR=Enable Optical Character Recognition (OCR) (Requires Windows 64-bit)
KeywordSearchGlobalSettingsPanel.Title=Global Keyword Search Settings
KeywordSearchIngestModule.init.badInitMsg=Keyword search server was not properly initialized, cannot run keyword search ingest.
# {0} - Reason for not connecting to Solr
@ -36,7 +38,7 @@ KeywordSearchResultFactory.createNodeForKey.noResultsFound.text=No results found
KeywordSearchResultFactory.query.exception.msg=Could not perform the query
OpenIDE-Module-Display-Category=Ingest Module
OpenIDE-Module-Long-Description=Keyword Search ingest module.\n\nThe module indexes files found in the disk image at ingest time.\nIt then periodically runs the search on the indexed files using one or more keyword lists (containing pure words and/or regular expressions) and posts results.\n\n\The module also contains additional tools integrated in the main GUI, such as keyword list configuration, keyword search bar in the top-right corner, extracted text viewer and search results viewer showing highlighted keywords found.
OpenIDE-Module-Long-Description=Keyword Search ingest module.\n\nThe module indexes files found in the disk image at ingest time.\nIt then periodically runs the search on the indexed files using one or more keyword lists (containing pure words and/or regular expressions) and posts results.\n\nThe module also contains additional tools integrated in the main GUI, such as keyword list configuration, keyword search bar in the top-right corner, extracted text viewer and search results viewer showing highlighted keywords found.
OpenIDE-Module-Name=KeywordSearch
OptionsCategory_Name_KeywordSearchOptions=Keyword Search
OptionsCategory_Keywords_KeywordSearchOptions=Keyword Search
@ -254,7 +256,6 @@ KeywordSearchJobSettingsPanel.languagesLabel.text=Scripts enabled for string ext
KeywordSearchGlobalLanguageSettingsPanel.enableUTF8Checkbox.text=Enable UTF8 text extraction
KeywordSearchGlobalLanguageSettingsPanel.ingestSettingsLabel.text=Ingest settings for string extraction from unknown file types (changes effective on next ingest):
KeywordSearchGlobalLanguageSettingsPanel.enableUTF16Checkbox.text=Enable UTF16LE and UTF16BE string extraction
KeywordSearchGlobalLanguageSettingsPanel.enableOcrCheckbox.text=Enable Optical Character Recognition (OCR)
KeywordSearchGlobalLanguageSettingsPanel.languagesLabel.text=Enabled scripts (languages):
KeywordSearchGlobalSearchSettingsPanel.timeRadioButton1.toolTipText=20 mins. (fastest ingest time)
KeywordSearchGlobalSearchSettingsPanel.timeRadioButton1.text=20 minutes (slowest feedback, fastest ingest)
@ -382,6 +383,7 @@ ExtractedContentPanel.pageTotalLabel.text=-
ExtractedContentPanel.pageOfLabel.text=of
ExtractedContentPanel.pageCurLabel.text=-
ExtractedContentPanel.pagesLabel.text=Page:
KeywordSearchGlobalSearchSettingsPanel.ocrCheckBox.text=Enable Optical Character Recognition (OCR)
TextZoomPanel.zoomInButton.text=
TextZoomPanel.zoomOutButton.text=
TextZoomPanel.zoomResetButton.text=Reset

View File

@ -186,7 +186,6 @@ KeywordSearchEditListPanel.selectAllMenuItem.text=\u3059\u3079\u3066\u9078\u629e
KeywordSearchFilterNode.getFileActions.openExternViewActLbl=\u5916\u90e8\u30d3\u30e5\u30fc\u30ef\u30fc\u3067\u958b\u304f Ctrl+E
KeywordSearchFilterNode.getFileActions.searchSameMd5=\u540c\u3058MD5\u30cf\u30c3\u30b7\u30e5\u3067\u30d5\u30a1\u30a4\u30eb\u3092\u691c\u7d22
KeywordSearchFilterNode.getFileActions.viewInNewWinActionLbl=\u65b0\u3057\u3044\u30a6\u30a3\u30f3\u30c9\u30a6\u3067\u8868\u793a
KeywordSearchGlobalLanguageSettingsPanel.enableOcrCheckbox.text=\u5149\u5b66\u6587\u5b57\u8a8d\u8b58(OCR)\u3092\u6709\u52b9\u5316
KeywordSearchGlobalLanguageSettingsPanel.enableUTF16Checkbox.text=UTF16LE\u304a\u3088\u3073UTF16BE\u6587\u5b57\u5217\u62bd\u51fa\u3092\u6709\u52b9\u5316
KeywordSearchGlobalLanguageSettingsPanel.enableUTF8Checkbox.text=UTF8\u30c6\u30ad\u30b9\u30c8\u62bd\u51fa\u3092\u6709\u52b9\u5316\u3059\u308b
KeywordSearchGlobalLanguageSettingsPanel.ingestSettingsLabel.text=\u672a\u77e5\u306e\u30d5\u30a1\u30a4\u30eb\u30bf\u30a4\u30d7\u304b\u3089\u306e\u6587\u5b57\u5217\u62bd\u51fa\u306e\u305f\u3081\u306e\u30a4\u30f3\u30b8\u30a7\u30b9\u30c8\u8a2d\u5b9a(\u5909\u66f4\u306f\u6b21\u306e\u30a4\u30f3\u30b8\u30a7\u30b9\u30c8\u3067\u6709\u52b9\u306b\u306a\u308a\u307e\u3059)\:

View File

@ -15,33 +15,31 @@
<Layout>
<DimensionLayout dim="0">
<Group type="103" groupAlignment="0" attributes="0">
<Group type="102" attributes="0">
<Group type="103" groupAlignment="0" attributes="0">
<Group type="102" alignment="0" attributes="0">
<EmptySpace min="-2" max="-2" attributes="0"/>
<Group type="103" groupAlignment="0" attributes="0">
<Component id="ingestSettingsLabel" alignment="0" min="-2" max="-2" attributes="0"/>
<Group type="102" alignment="0" attributes="0">
<Group type="103" groupAlignment="1" attributes="0">
<Component id="languagesLabel" alignment="0" min="-2" max="-2" attributes="0"/>
<Component id="langPanel" min="-2" max="-2" attributes="0"/>
</Group>
<EmptySpace type="unrelated" min="-2" max="-2" attributes="0"/>
<Component id="ingestWarningLabel" pref="360" max="32767" attributes="0"/>
</Group>
</Group>
</Group>
<Group type="102" attributes="0">
<Group type="103" groupAlignment="0" attributes="0">
<Component id="languagesLabel" alignment="0" min="-2" max="-2" attributes="0"/>
<Group type="102" alignment="0" attributes="0">
<EmptySpace min="-2" pref="26" max="-2" attributes="0"/>
<EmptySpace min="-2" pref="16" max="-2" attributes="0"/>
<Group type="103" groupAlignment="0" max="-2" attributes="0">
<Component id="enableUTF16Checkbox" min="-2" max="-2" attributes="0"/>
<Component id="enableUTF8Checkbox" alignment="0" min="-2" max="-2" attributes="0"/>
<Component id="enableOcrCheckbox" alignment="0" min="-2" max="-2" attributes="0"/>
</Group>
</Group>
<Component id="ingestSettingsLabel" alignment="0" min="-2" max="-2" attributes="0"/>
</Group>
<EmptySpace min="-2" max="-2" attributes="0"/>
<EmptySpace min="0" pref="0" max="32767" attributes="0"/>
</Group>
</Group>
<EmptySpace max="-2" attributes="0"/>
</Group>
</Group>
</DimensionLayout>
@ -50,18 +48,16 @@
<Group type="102" alignment="0" attributes="0">
<EmptySpace max="-2" attributes="0"/>
<Component id="ingestSettingsLabel" min="-2" max="-2" attributes="0"/>
<EmptySpace type="unrelated" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Group type="103" groupAlignment="0" attributes="0">
<Group type="102" attributes="0">
<Component id="enableOcrCheckbox" min="-2" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Component id="enableUTF16Checkbox" min="-2" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Component id="enableUTF8Checkbox" min="-2" max="-2" attributes="0"/>
<EmptySpace type="unrelated" max="-2" attributes="0"/>
<Component id="languagesLabel" min="-2" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Component id="langPanel" pref="380" max="32767" attributes="0"/>
<EmptySpace min="-2" max="-2" attributes="0"/>
<Component id="langPanel" pref="408" max="32767" attributes="0"/>
</Group>
<Group type="102" attributes="0">
<EmptySpace min="0" pref="0" max="32767" attributes="0"/>
@ -105,7 +101,7 @@
</DimensionLayout>
<DimensionLayout dim="1">
<Group type="103" groupAlignment="0" attributes="0">
<EmptySpace min="0" pref="378" max="32767" attributes="0"/>
<EmptySpace min="0" pref="406" max="32767" attributes="0"/>
</Group>
</DimensionLayout>
</Layout>
@ -139,16 +135,6 @@
</Property>
</Properties>
</Component>
<Component class="javax.swing.JCheckBox" name="enableOcrCheckbox">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/keywordsearch/Bundle.properties" key="KeywordSearchGlobalLanguageSettingsPanel.enableOcrCheckbox.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
</Properties>
<Events>
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="enableOcrCheckboxActionPerformed"/>
</Events>
</Component>
<Component class="javax.swing.JLabel" name="ingestWarningLabel">
<Properties>
<Property name="icon" type="javax.swing.Icon" editor="org.netbeans.modules.form.editors2.IconEditor">

View File

@ -71,12 +71,6 @@ class KeywordSearchGlobalLanguageSettingsPanel extends javax.swing.JPanel implem
initScriptsCheckBoxes();
reloadScriptsCheckBoxes();
if (!PlatformUtil.isWindowsOS() || !PlatformUtil.is64BitOS()) {
enableOcrCheckbox.setText("Enable Optical Character Recognition (OCR) (Requires Windows 64-bit)");
enableOcrCheckbox.setSelected(false);
enableOcrCheckbox.setEnabled(false);
}
//allow panel to toggle its enabled status while it is open based on ingest events
IngestManager.getInstance().addIngestJobEventListener(new PropertyChangeListener() {
@Override
@ -136,9 +130,6 @@ class KeywordSearchGlobalLanguageSettingsPanel extends javax.swing.JPanel implem
= Boolean.parseBoolean(KeywordSearchSettings.getStringExtractOption(StringsExtractOptions.EXTRACT_UTF8.toString()));
enableUTF8Checkbox.setSelected(utf8);
boolean ocr = KeywordSearchSettings.getOcrOption();
enableOcrCheckbox.setSelected(ocr);
final List<SCRIPT> serviceScripts = KeywordSearchSettings.getStringExtractScripts();
final int components = checkPanel.getComponentCount();
@ -170,7 +161,6 @@ class KeywordSearchGlobalLanguageSettingsPanel extends javax.swing.JPanel implem
ingestWarningLabel.setVisible(ingestRunning);
enableUTF16Checkbox.setEnabled(!ingestRunning);
enableUTF8Checkbox.setEnabled(!ingestRunning);
enableOcrCheckbox.setEnabled(!ingestRunning);
}
/**
@ -188,7 +178,6 @@ class KeywordSearchGlobalLanguageSettingsPanel extends javax.swing.JPanel implem
enableUTF8Checkbox = new javax.swing.JCheckBox();
enableUTF16Checkbox = new javax.swing.JCheckBox();
ingestSettingsLabel = new javax.swing.JLabel();
enableOcrCheckbox = new javax.swing.JCheckBox();
ingestWarningLabel = new javax.swing.JLabel();
org.openide.awt.Mnemonics.setLocalizedText(languagesLabel, org.openide.util.NbBundle.getMessage(KeywordSearchGlobalLanguageSettingsPanel.class, "KeywordSearchGlobalLanguageSettingsPanel.languagesLabel.text")); // NOI18N
@ -205,7 +194,7 @@ class KeywordSearchGlobalLanguageSettingsPanel extends javax.swing.JPanel implem
);
checkPanelLayout.setVerticalGroup(
checkPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGap(0, 378, Short.MAX_VALUE)
.addGap(0, 406, Short.MAX_VALUE)
);
langPanel.setViewportView(checkPanel);
@ -226,13 +215,6 @@ class KeywordSearchGlobalLanguageSettingsPanel extends javax.swing.JPanel implem
org.openide.awt.Mnemonics.setLocalizedText(ingestSettingsLabel, org.openide.util.NbBundle.getMessage(KeywordSearchGlobalLanguageSettingsPanel.class, "KeywordSearchGlobalLanguageSettingsPanel.ingestSettingsLabel.text")); // NOI18N
org.openide.awt.Mnemonics.setLocalizedText(enableOcrCheckbox, org.openide.util.NbBundle.getMessage(KeywordSearchGlobalLanguageSettingsPanel.class, "KeywordSearchGlobalLanguageSettingsPanel.enableOcrCheckbox.text")); // NOI18N
enableOcrCheckbox.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
enableOcrCheckboxActionPerformed(evt);
}
});
ingestWarningLabel.setIcon(new javax.swing.ImageIcon(getClass().getResource("/org/sleuthkit/autopsy/modules/hashdatabase/warning16.png"))); // NOI18N
org.openide.awt.Mnemonics.setLocalizedText(ingestWarningLabel, org.openide.util.NbBundle.getMessage(KeywordSearchGlobalLanguageSettingsPanel.class, "KeywordSearchGlobalLanguageSettingsPanel.ingestWarningLabel.text")); // NOI18N
@ -240,24 +222,23 @@ class KeywordSearchGlobalLanguageSettingsPanel extends javax.swing.JPanel implem
this.setLayout(layout);
layout.setHorizontalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup()
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup()
.addContainerGap()
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(ingestSettingsLabel)
.addGroup(layout.createSequentialGroup()
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING)
.addComponent(languagesLabel, javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(langPanel, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
.addComponent(langPanel, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
.addComponent(ingestWarningLabel, javax.swing.GroupLayout.DEFAULT_SIZE, 360, Short.MAX_VALUE))))
.addComponent(ingestWarningLabel, javax.swing.GroupLayout.DEFAULT_SIZE, 360, Short.MAX_VALUE))
.addGroup(layout.createSequentialGroup()
.addGap(26, 26, 26)
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(languagesLabel)
.addGroup(layout.createSequentialGroup()
.addGap(16, 16, 16)
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false)
.addComponent(enableUTF16Checkbox)
.addComponent(enableUTF8Checkbox)
.addComponent(enableOcrCheckbox))))
.addComponent(enableUTF8Checkbox)))
.addComponent(ingestSettingsLabel))
.addGap(0, 0, Short.MAX_VALUE)))
.addContainerGap())
);
layout.setVerticalGroup(
@ -265,18 +246,16 @@ class KeywordSearchGlobalLanguageSettingsPanel extends javax.swing.JPanel implem
.addGroup(layout.createSequentialGroup()
.addContainerGap()
.addComponent(ingestSettingsLabel)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup()
.addComponent(enableOcrCheckbox)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(enableUTF16Checkbox)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(enableUTF8Checkbox)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
.addComponent(languagesLabel)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(langPanel, javax.swing.GroupLayout.DEFAULT_SIZE, 380, Short.MAX_VALUE))
.addComponent(langPanel, javax.swing.GroupLayout.DEFAULT_SIZE, 408, Short.MAX_VALUE))
.addGroup(layout.createSequentialGroup()
.addGap(0, 0, Short.MAX_VALUE)
.addComponent(ingestWarningLabel)))
@ -301,13 +280,8 @@ class KeywordSearchGlobalLanguageSettingsPanel extends javax.swing.JPanel implem
firePropertyChange(OptionsPanelController.PROP_CHANGED, null, null);
}//GEN-LAST:event_enableUTF16CheckboxActionPerformed
private void enableOcrCheckboxActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_enableOcrCheckboxActionPerformed
firePropertyChange(OptionsPanelController.PROP_CHANGED, null, null);
}//GEN-LAST:event_enableOcrCheckboxActionPerformed
// Variables declaration - do not modify//GEN-BEGIN:variables
private javax.swing.JPanel checkPanel;
private javax.swing.JCheckBox enableOcrCheckbox;
private javax.swing.JCheckBox enableUTF16Checkbox;
private javax.swing.JCheckBox enableUTF8Checkbox;
private javax.swing.JLabel ingestSettingsLabel;
@ -322,7 +296,6 @@ class KeywordSearchGlobalLanguageSettingsPanel extends javax.swing.JPanel implem
Boolean.toString(enableUTF8Checkbox.isSelected()));
KeywordSearchSettings.setStringExtractOption(StringsExtractOptions.EXTRACT_UTF16.toString(),
Boolean.toString(enableUTF16Checkbox.isSelected()));
KeywordSearchSettings.setOcrOption(enableOcrCheckbox.isSelected());
if (toUpdate != null) {
KeywordSearchSettings.setStringExtractScripts(toUpdate);

View File

@ -23,6 +23,7 @@
<Group type="102" attributes="0">
<EmptySpace max="-2" attributes="0"/>
<Group type="103" groupAlignment="0" attributes="0">
<Component id="ingestWarningLabel" alignment="0" max="32767" attributes="0"/>
<Group type="102" attributes="0">
<Group type="103" groupAlignment="0" attributes="0">
<Group type="102" alignment="0" attributes="0">
@ -30,17 +31,23 @@
<EmptySpace max="-2" attributes="0"/>
<Component id="settingsSeparator" min="-2" pref="326" max="-2" attributes="0"/>
</Group>
<Group type="102" alignment="0" attributes="0">
<Component id="informationLabel" min="-2" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Component id="informationSeparator" min="-2" pref="309" max="-2" attributes="0"/>
</Group>
<Group type="102" attributes="0">
<EmptySpace min="10" pref="10" max="-2" attributes="0"/>
<Group type="103" groupAlignment="0" attributes="0">
<Component id="skipNSRLCheckBox" min="-2" max="-2" attributes="0"/>
<Component id="showSnippetsCB" alignment="0" min="-2" max="-2" attributes="0"/>
<Group type="102" attributes="0">
<Component id="ocrCheckBox" alignment="0" min="-2" max="-2" attributes="0"/>
</Group>
</Group>
<Group type="102" alignment="0" attributes="0">
<Component id="informationLabel" min="-2" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Component id="informationSeparator" min="-2" pref="309" max="-2" attributes="0"/>
</Group>
<Group type="102" alignment="0" attributes="0">
<EmptySpace min="10" pref="10" max="-2" attributes="0"/>
<Group type="103" groupAlignment="0" attributes="0">
<Group type="102" alignment="0" attributes="0">
<Component id="filesIndexedLabel" linkSize="1" min="-2" max="-2" attributes="0"/>
<EmptySpace type="separate" max="-2" attributes="0"/>
<Component id="filesIndexedValue" min="-2" max="-2" attributes="0"/>
@ -66,7 +73,6 @@
</Group>
<EmptySpace min="0" pref="0" max="32767" attributes="0"/>
</Group>
<Component id="ingestWarningLabel" alignment="0" max="32767" attributes="0"/>
</Group>
<EmptySpace max="-2" attributes="0"/>
</Group>
@ -85,6 +91,8 @@
<EmptySpace max="-2" attributes="0"/>
<Component id="showSnippetsCB" min="-2" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Component id="ocrCheckBox" min="-2" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Component id="frequencyLabel" min="-2" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Component id="timeRadioButton1" min="-2" max="-2" attributes="0"/>
@ -113,7 +121,7 @@
</Group>
<EmptySpace type="unrelated" max="-2" attributes="0"/>
<Component id="ingestWarningLabel" min="-2" max="-2" attributes="0"/>
<EmptySpace pref="66" max="32767" attributes="0"/>
<EmptySpace pref="43" max="32767" attributes="0"/>
</Group>
</Group>
</DimensionLayout>
@ -270,5 +278,15 @@
</Property>
</Properties>
</Component>
<Component class="javax.swing.JCheckBox" name="ocrCheckBox">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/keywordsearch/Bundle.properties" key="KeywordSearchGlobalSearchSettingsPanel.ocrCheckBox.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
</Properties>
<Events>
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="ocrCheckBoxActionPerformed"/>
</Events>
</Component>
</SubComponents>
</Form>

View File

@ -23,8 +23,10 @@ import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.util.logging.Level;
import org.netbeans.spi.options.OptionsPanelController;
import org.openide.util.NbBundle;
import org.sleuthkit.autopsy.corecomponents.OptionsPanel;
import org.sleuthkit.autopsy.coreutils.Logger;
import org.sleuthkit.autopsy.coreutils.PlatformUtil;
import org.sleuthkit.autopsy.ingest.IngestManager;
import org.sleuthkit.autopsy.keywordsearch.KeywordSearchIngestModule.UpdateFrequency;
@ -47,9 +49,11 @@ class KeywordSearchGlobalSearchSettingsPanel extends javax.swing.JPanel implemen
private void activateWidgets() {
skipNSRLCheckBox.setSelected(KeywordSearchSettings.getSkipKnown());
showSnippetsCB.setSelected(KeywordSearchSettings.getShowSnippets());
ocrCheckBox.setSelected(KeywordSearchSettings.getOcrOption());
boolean ingestRunning = IngestManager.getInstance().isIngestRunning();
ingestWarningLabel.setVisible(ingestRunning);
skipNSRLCheckBox.setEnabled(!ingestRunning);
ocrCheckBox.setEnabled(!ingestRunning);
setTimeSettingEnabled(!ingestRunning);
final UpdateFrequency curFreq = KeywordSearchSettings.getUpdateFrequency();
@ -104,6 +108,7 @@ class KeywordSearchGlobalSearchSettingsPanel extends javax.swing.JPanel implemen
showSnippetsCB = new javax.swing.JCheckBox();
timeRadioButton5 = new javax.swing.JRadioButton();
ingestWarningLabel = new javax.swing.JLabel();
ocrCheckBox = new javax.swing.JCheckBox();
skipNSRLCheckBox.setText(org.openide.util.NbBundle.getMessage(KeywordSearchGlobalSearchSettingsPanel.class, "KeywordSearchGlobalSearchSettingsPanel.skipNSRLCheckBox.text")); // NOI18N
skipNSRLCheckBox.setToolTipText(org.openide.util.NbBundle.getMessage(KeywordSearchGlobalSearchSettingsPanel.class, "KeywordSearchGlobalSearchSettingsPanel.skipNSRLCheckBox.toolTipText")); // NOI18N
@ -177,6 +182,13 @@ class KeywordSearchGlobalSearchSettingsPanel extends javax.swing.JPanel implemen
ingestWarningLabel.setIcon(new javax.swing.ImageIcon(getClass().getResource("/org/sleuthkit/autopsy/modules/hashdatabase/warning16.png"))); // NOI18N
ingestWarningLabel.setText(org.openide.util.NbBundle.getMessage(KeywordSearchGlobalSearchSettingsPanel.class, "KeywordSearchGlobalSearchSettingsPanel.ingestWarningLabel.text")); // NOI18N
ocrCheckBox.setText(org.openide.util.NbBundle.getMessage(KeywordSearchGlobalSearchSettingsPanel.class, "KeywordSearchGlobalSearchSettingsPanel.ocrCheckBox.text")); // NOI18N
ocrCheckBox.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
ocrCheckBoxActionPerformed(evt);
}
});
javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
this.setLayout(layout);
layout.setHorizontalGroup(
@ -184,12 +196,19 @@ class KeywordSearchGlobalSearchSettingsPanel extends javax.swing.JPanel implemen
.addGroup(layout.createSequentialGroup()
.addContainerGap()
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(ingestWarningLabel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addGroup(layout.createSequentialGroup()
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup()
.addComponent(settingsLabel)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(settingsSeparator, javax.swing.GroupLayout.PREFERRED_SIZE, 326, javax.swing.GroupLayout.PREFERRED_SIZE))
.addGroup(layout.createSequentialGroup()
.addGap(10, 10, 10)
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(skipNSRLCheckBox)
.addComponent(showSnippetsCB)
.addComponent(ocrCheckBox)))
.addGroup(layout.createSequentialGroup()
.addComponent(informationLabel)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
@ -197,8 +216,6 @@ class KeywordSearchGlobalSearchSettingsPanel extends javax.swing.JPanel implemen
.addGroup(layout.createSequentialGroup()
.addGap(10, 10, 10)
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(skipNSRLCheckBox)
.addComponent(showSnippetsCB)
.addGroup(layout.createSequentialGroup()
.addComponent(filesIndexedLabel)
.addGap(18, 18, 18)
@ -216,8 +233,7 @@ class KeywordSearchGlobalSearchSettingsPanel extends javax.swing.JPanel implemen
.addComponent(chunksLabel)
.addGap(18, 18, 18)
.addComponent(chunksValLabel)))))
.addGap(0, 0, Short.MAX_VALUE))
.addComponent(ingestWarningLabel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
.addGap(0, 0, Short.MAX_VALUE)))
.addContainerGap())
);
@ -235,6 +251,8 @@ class KeywordSearchGlobalSearchSettingsPanel extends javax.swing.JPanel implemen
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(showSnippetsCB)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(ocrCheckBox)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(frequencyLabel)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(timeRadioButton1)
@ -260,7 +278,7 @@ class KeywordSearchGlobalSearchSettingsPanel extends javax.swing.JPanel implemen
.addComponent(chunksValLabel))
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
.addComponent(ingestWarningLabel)
.addContainerGap(66, Short.MAX_VALUE))
.addContainerGap(43, Short.MAX_VALUE))
);
}// </editor-fold>//GEN-END:initComponents
@ -292,6 +310,10 @@ class KeywordSearchGlobalSearchSettingsPanel extends javax.swing.JPanel implemen
firePropertyChange(OptionsPanelController.PROP_CHANGED, null, null);
}//GEN-LAST:event_timeRadioButton4ActionPerformed
private void ocrCheckBoxActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_ocrCheckBoxActionPerformed
firePropertyChange(OptionsPanelController.PROP_CHANGED, null, null);
}//GEN-LAST:event_ocrCheckBoxActionPerformed
// Variables declaration - do not modify//GEN-BEGIN:variables
private javax.swing.JLabel chunksLabel;
private javax.swing.JLabel chunksValLabel;
@ -301,6 +323,7 @@ class KeywordSearchGlobalSearchSettingsPanel extends javax.swing.JPanel implemen
private javax.swing.JLabel informationLabel;
private javax.swing.JSeparator informationSeparator;
private javax.swing.JLabel ingestWarningLabel;
private javax.swing.JCheckBox ocrCheckBox;
private javax.swing.JLabel settingsLabel;
private javax.swing.JSeparator settingsSeparator;
private javax.swing.JCheckBox showSnippetsCB;
@ -318,6 +341,7 @@ class KeywordSearchGlobalSearchSettingsPanel extends javax.swing.JPanel implemen
KeywordSearchSettings.setSkipKnown(skipNSRLCheckBox.isSelected());
KeywordSearchSettings.setUpdateFrequency(getSelectedTimeValue());
KeywordSearchSettings.setShowSnippets(showSnippetsCB.isSelected());
KeywordSearchSettings.setOcrOption(ocrCheckBox.isSelected());
}
@Override
@ -349,6 +373,7 @@ class KeywordSearchGlobalSearchSettingsPanel extends javax.swing.JPanel implemen
return UpdateFrequency.DEFAULT;
}
@NbBundle.Messages({"KeywordSearchGlobalSearchSettingsPanel.customizeComponents.windowsOCR=Enable Optical Character Recognition (OCR) (Requires Windows 64-bit)"})
private void customizeComponents() {
timeGroup.add(timeRadioButton1);
@ -366,6 +391,12 @@ class KeywordSearchGlobalSearchSettingsPanel extends javax.swing.JPanel implemen
logger.log(Level.WARNING, "Could not get number of indexed files/chunks"); //NON-NLS
}
if (!PlatformUtil.isWindowsOS() || !PlatformUtil.is64BitOS()) {
ocrCheckBox.setText(Bundle.KeywordSearchGlobalSearchSettingsPanel_customizeComponents_windowsOCR());
ocrCheckBox.setSelected(false);
ocrCheckBox.setEnabled(false);
}
KeywordSearch.addNumIndexedFilesChangeListener(
new PropertyChangeListener() {
@Override

View File

@ -88,7 +88,7 @@ ExtractZone_progress_Msg=Extracting :Zone.Identifer files
ExtractZone_Restricted=Restricted Sites Zone
ExtractZone_Trusted=Trusted Sites Zone
OpenIDE-Module-Display-Category=Ingest Module
OpenIDE-Module-Long-Description=Recent Activity ingest module.\n\n\The module extracts useful information about the recent user activity on the disk image being ingested, such as:\n\n- Recently open documents,\n- Web activity (sites visited, stored cookies, book marked sites, search engine queries, file downloads),\n- Recently attached devices,\n- Installed programs.\n\nThe module currently supports Windows only disk images.\nThe plugin is also fully functional when deployed on Windows version of Autopsy.
OpenIDE-Module-Long-Description=Recent Activity ingest module.\n\nThe module extracts useful information about the recent user activity on the disk image being ingested, such as:\n\n- Recently open documents,\n- Web activity (sites visited, stored cookies, book marked sites, search engine queries, file downloads),\n- Recently attached devices,\n- Installed programs.\n\nThe module currently supports Windows only disk images.\nThe plugin is also fully functional when deployed on Windows version of Autopsy.
OpenIDE-Module-Name=RecentActivity
OpenIDE-Module-Short-Description=Recent Activity finder ingest module
Chrome.moduleName=Chromium

View File

@ -474,7 +474,7 @@ class Chromium extends Extract {
}
List<HashMap<String, Object>> tempList = this.dbConnect(temps, COOKIE_QUERY);
logger.log(Level.INFO, "{0}- Now getting cookies from {1} with {2}artifacts identified.", new Object[]{moduleName, temps, tempList.size()}); //NON-NLS
logger.log(Level.INFO, "{0}- Now getting cookies from {1} with {2} artifacts identified.", new Object[]{moduleName, temps, tempList.size()}); //NON-NLS
for (HashMap<String, Object> result : tempList) {
Collection<BlackboardAttribute> bbattributes = new ArrayList<>();
bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_URL,

View File

@ -1784,7 +1784,8 @@ class ExtractRegistry extends Extract {
line = line.trim();
usedTime = Long.valueOf(0);
if (!line.contains("**") && !line.contains("----------") && !line.contains("LastWrite")
&& !line.contains(SECTION_DIVIDER) && !line.isEmpty() && !line.contains("TrustRecords")) {
&& !line.contains(SECTION_DIVIDER) && !line.isEmpty() && !line.contains("TrustRecords")
&& !line.contains("VBAWarnings =")) {
// Columns are
// Date : <File Name>/<Website>
// Split line on " : " which is the record delimiter between position and file

View File

@ -116,7 +116,7 @@ final class ExtractZoneIdentifier extends Extract {
/**
* Process a single Zone Identifier file.
*
* @param context IngetJobContext
* @param context IngestJobContext
* @param dataSource Content
* @param zoneFile Zone Indentifier file
* @param associatedObjectArtifacts List for TSK_ASSOCIATED_OBJECT artifacts
@ -149,7 +149,7 @@ final class ExtractZoneIdentifier extends Extract {
if (!knownPathIDs.contains(downloadFile.getDataSourceObjectId())) {
// The zone identifier file is the parent of this artifact
// because it is the file we parsed to get the data
BlackboardArtifact downloadBba = createDownloadArtifact(zoneFile, zoneInfo);
BlackboardArtifact downloadBba = createDownloadArtifact(zoneFile, zoneInfo, downloadFile);
if (downloadBba != null) {
downloadArtifacts.add(downloadBba);
// create a TSK_ASSOCIATED_OBJECT for the downloaded file, associating it with the TSK_WEB_DOWNLOAD artifact.
@ -227,16 +227,24 @@ final class ExtractZoneIdentifier extends Extract {
*
* @param zoneFile Zone identifier file
* @param zoneInfo ZoneIdentifierInfo file wrapper object
* @param downloadFile The file associated with the zone identifier
*
* @return BlackboardArifact for the given parameters
*/
private BlackboardArtifact createDownloadArtifact(AbstractFile zoneFile, ZoneIdentifierInfo zoneInfo) {
private BlackboardArtifact createDownloadArtifact(AbstractFile zoneFile, ZoneIdentifierInfo zoneInfo, AbstractFile downloadFile) {
String downloadFilePath = downloadFile.getParentPath() + downloadFile.getName();
Collection<BlackboardAttribute> bbattributes = createDownloadAttributes(
null, null,
downloadFilePath, null,
zoneInfo.getURL(), null,
(zoneInfo.getURL() != null ? NetworkUtils.extractDomain(zoneInfo.getURL()) : ""),
null);
if (zoneInfo.getZoneIdAsString() != null) {
bbattributes.add(new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_COMMENT,
RecentActivityExtracterModuleFactory.getModuleName(),
zoneInfo.getZoneIdAsString()));
}
return createArtifactWithAttributes(TSK_WEB_DOWNLOAD, zoneFile, bbattributes);
}

View File

@ -156,7 +156,7 @@
</copy>
<property name="app.property.file" value="${zip-tmp}/${app.name}/etc/${app.name}.conf" />
<var name="jvm-value" value="--branding ${app.name} -J-Xms24m -J-Xmx4G -J-Xverify:none -J-XX:+UseG1GC -J-XX:+UseStringDeduplication"/>
<var name="jvm-value" value="--branding ${app.name} -J-Xms24m -J-Xmx4G -J-Xverify:none -J-XX:+UseG1GC -J-XX:+UseStringDeduplication -J-Dprism.order=sw"/>
<!-- for Japanese localized version add option: -Duser.language=ja -->