mirror of
https://github.com/overcuriousity/autopsy-flatpak.git
synced 2025-07-17 10:17:41 +00:00
Resolve merge conflict between columns reordering and tag column color
This commit is contained in:
commit
b957ebd795
@ -39,6 +39,7 @@ import org.openide.util.Lookup;
|
||||
import org.openide.util.NbBundle;
|
||||
import org.sleuthkit.autopsy.corecomponentinterfaces.DataSourceProcessor;
|
||||
import org.sleuthkit.autopsy.coreutils.Logger;
|
||||
import org.sleuthkit.autopsy.datasourceprocessors.RawDSProcessor;
|
||||
|
||||
/**
|
||||
* visual component for the first panel of add image wizard. Allows the user to
|
||||
@ -92,7 +93,8 @@ final class AddImageWizardChooseDataSourceVisual extends JPanel {
|
||||
datasourceProcessorsMap.remove(LocalDiskDSProcessor.getType());
|
||||
}
|
||||
coreDSPTypes.add(LocalFilesDSProcessor.getType());
|
||||
|
||||
coreDSPTypes.add(RawDSProcessor.getType());
|
||||
|
||||
for (String dspType : coreDSPTypes) {
|
||||
typeComboBox.addItem(dspType);
|
||||
}
|
||||
|
@ -78,7 +78,6 @@ public class ImageFilePanel extends JPanel implements DocumentListener {
|
||||
|
||||
this.contextName = context;
|
||||
|
||||
createTimeZoneList();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -89,6 +88,7 @@ public class ImageFilePanel extends JPanel implements DocumentListener {
|
||||
ImageFilePanel instance = new ImageFilePanel(context, fileChooserFilters);
|
||||
|
||||
instance.postInit();
|
||||
instance.createTimeZoneList();
|
||||
|
||||
return instance;
|
||||
}
|
||||
|
@ -21,10 +21,7 @@
|
||||
</DimensionLayout>
|
||||
<DimensionLayout dim="1">
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<Group type="102" alignment="0" attributes="0">
|
||||
<Component id="jPanel1" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace min="0" pref="0" max="32767" attributes="0"/>
|
||||
</Group>
|
||||
<Component id="jPanel1" alignment="0" max="32767" attributes="0"/>
|
||||
</Group>
|
||||
</DimensionLayout>
|
||||
</Layout>
|
||||
@ -39,11 +36,11 @@
|
||||
<Layout>
|
||||
<DimensionLayout dim="0">
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<Group type="102" alignment="1" attributes="0">
|
||||
<Group type="102" alignment="0" attributes="0">
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Group type="103" groupAlignment="1" attributes="0">
|
||||
<Component id="jSplitPane1" max="32767" attributes="0"/>
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<Component id="panelDescriptionLabel" max="32767" attributes="0"/>
|
||||
<Component id="jScrollPane2" max="32767" attributes="0"/>
|
||||
</Group>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
</Group>
|
||||
@ -55,7 +52,7 @@
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Component id="panelDescriptionLabel" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Component id="jSplitPane1" max="32767" attributes="0"/>
|
||||
<Component id="jScrollPane2" pref="458" max="32767" attributes="0"/>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
</Group>
|
||||
</Group>
|
||||
@ -69,132 +66,138 @@
|
||||
</Property>
|
||||
</Properties>
|
||||
</Component>
|
||||
<Container class="javax.swing.JSplitPane" name="jSplitPane1">
|
||||
<Properties>
|
||||
<Property name="dividerLocation" type="int" value="400"/>
|
||||
<Property name="dividerSize" type="int" value="1"/>
|
||||
</Properties>
|
||||
<Container class="javax.swing.JScrollPane" name="jScrollPane2">
|
||||
|
||||
<Layout class="org.netbeans.modules.form.compat2.layouts.support.JSplitPaneSupportLayout"/>
|
||||
<Layout class="org.netbeans.modules.form.compat2.layouts.support.JScrollPaneSupportLayout"/>
|
||||
<SubComponents>
|
||||
<Container class="javax.swing.JPanel" name="modifyTagTypesListPanel">
|
||||
<Constraints>
|
||||
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.support.JSplitPaneSupportLayout" value="org.netbeans.modules.form.compat2.layouts.support.JSplitPaneSupportLayout$JSplitPaneConstraintsDescription">
|
||||
<JSplitPaneConstraints position="left"/>
|
||||
</Constraint>
|
||||
</Constraints>
|
||||
<Container class="javax.swing.JSplitPane" name="jSplitPane1">
|
||||
<Properties>
|
||||
<Property name="dividerLocation" type="int" value="400"/>
|
||||
<Property name="dividerSize" type="int" value="1"/>
|
||||
</Properties>
|
||||
|
||||
<Layout>
|
||||
<DimensionLayout dim="0">
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<Group type="102" alignment="0" attributes="0">
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<Component id="tagTypesListLabel" alignment="0" max="32767" attributes="0"/>
|
||||
<Group type="102" alignment="0" attributes="0">
|
||||
<Component id="newTagNameButton" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Component id="deleteTagNameButton" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace min="0" pref="113" max="32767" attributes="0"/>
|
||||
</Group>
|
||||
<Component id="jScrollPane1" alignment="0" max="32767" attributes="0"/>
|
||||
</Group>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
</Group>
|
||||
</Group>
|
||||
</DimensionLayout>
|
||||
<DimensionLayout dim="1">
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<Group type="102" alignment="0" attributes="0">
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Component id="tagTypesListLabel" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Component id="jScrollPane1" pref="383" max="32767" attributes="0"/>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Group type="103" groupAlignment="3" attributes="0">
|
||||
<Component id="newTagNameButton" alignment="3" min="-2" max="-2" attributes="0"/>
|
||||
<Component id="deleteTagNameButton" alignment="3" min="-2" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
</Group>
|
||||
</Group>
|
||||
</DimensionLayout>
|
||||
</Layout>
|
||||
<Layout class="org.netbeans.modules.form.compat2.layouts.support.JSplitPaneSupportLayout"/>
|
||||
<SubComponents>
|
||||
<Component class="javax.swing.JLabel" name="tagTypesListLabel">
|
||||
<Properties>
|
||||
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/casemodule/services/Bundle.properties" key="TagOptionsPanel.tagTypesListLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
</Component>
|
||||
<Container class="javax.swing.JScrollPane" name="jScrollPane1">
|
||||
<AuxValues>
|
||||
<AuxValue name="autoScrollPane" type="java.lang.Boolean" value="true"/>
|
||||
</AuxValues>
|
||||
<Container class="javax.swing.JPanel" name="modifyTagTypesListPanel">
|
||||
<Constraints>
|
||||
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.support.JSplitPaneSupportLayout" value="org.netbeans.modules.form.compat2.layouts.support.JSplitPaneSupportLayout$JSplitPaneConstraintsDescription">
|
||||
<JSplitPaneConstraints position="left"/>
|
||||
</Constraint>
|
||||
</Constraints>
|
||||
|
||||
<Layout class="org.netbeans.modules.form.compat2.layouts.support.JScrollPaneSupportLayout"/>
|
||||
<Layout>
|
||||
<DimensionLayout dim="0">
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<Group type="102" attributes="0">
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<Component id="jScrollPane1" alignment="1" max="32767" attributes="0"/>
|
||||
<Component id="tagTypesListLabel" alignment="0" max="32767" attributes="0"/>
|
||||
<Group type="102" attributes="0">
|
||||
<Component id="newTagNameButton" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Component id="deleteTagNameButton" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace min="0" pref="113" max="32767" attributes="0"/>
|
||||
</Group>
|
||||
</Group>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
</Group>
|
||||
</Group>
|
||||
</DimensionLayout>
|
||||
<DimensionLayout dim="1">
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<Group type="102" attributes="0">
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Component id="tagTypesListLabel" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Component id="jScrollPane1" pref="381" max="32767" attributes="0"/>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Group type="103" groupAlignment="3" attributes="0">
|
||||
<Component id="newTagNameButton" alignment="3" min="-2" max="-2" attributes="0"/>
|
||||
<Component id="deleteTagNameButton" alignment="3" min="-2" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
</Group>
|
||||
</Group>
|
||||
</DimensionLayout>
|
||||
</Layout>
|
||||
<SubComponents>
|
||||
<Component class="javax.swing.JList" name="tagNamesList">
|
||||
<Component class="javax.swing.JLabel" name="tagTypesListLabel">
|
||||
<Properties>
|
||||
<Property name="model" type="javax.swing.ListModel" editor="org.netbeans.modules.form.editors2.ListModelEditor">
|
||||
<StringArray count="0"/>
|
||||
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/casemodule/services/Bundle.properties" key="TagOptionsPanel.tagTypesListLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</Property>
|
||||
<Property name="selectionMode" type="int" value="0"/>
|
||||
</Properties>
|
||||
</Component>
|
||||
<Container class="javax.swing.JScrollPane" name="jScrollPane1">
|
||||
<AuxValues>
|
||||
<AuxValue name="JavaCodeGenerator_TypeParameters" type="java.lang.String" value="<org.sleuthkit.autopsy.casemodule.services.TagNameDefiniton>"/>
|
||||
<AuxValue name="autoScrollPane" type="java.lang.Boolean" value="true"/>
|
||||
</AuxValues>
|
||||
|
||||
<Layout class="org.netbeans.modules.form.compat2.layouts.support.JScrollPaneSupportLayout"/>
|
||||
<SubComponents>
|
||||
<Component class="javax.swing.JList" name="tagNamesList">
|
||||
<Properties>
|
||||
<Property name="model" type="javax.swing.ListModel" editor="org.netbeans.modules.form.editors2.ListModelEditor">
|
||||
<StringArray count="0"/>
|
||||
</Property>
|
||||
<Property name="selectionMode" type="int" value="0"/>
|
||||
</Properties>
|
||||
<AuxValues>
|
||||
<AuxValue name="JavaCodeGenerator_TypeParameters" type="java.lang.String" value="<org.sleuthkit.autopsy.casemodule.services.TagNameDefiniton>"/>
|
||||
</AuxValues>
|
||||
</Component>
|
||||
</SubComponents>
|
||||
</Container>
|
||||
<Component class="javax.swing.JButton" name="newTagNameButton">
|
||||
<Properties>
|
||||
<Property name="icon" type="javax.swing.Icon" editor="org.netbeans.modules.form.editors2.IconEditor">
|
||||
<Image iconType="3" name="/org/sleuthkit/autopsy/images/add-tag.png"/>
|
||||
</Property>
|
||||
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/casemodule/services/Bundle.properties" key="TagOptionsPanel.newTagNameButton.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
<Events>
|
||||
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="newTagNameButtonActionPerformed"/>
|
||||
</Events>
|
||||
</Component>
|
||||
<Component class="javax.swing.JButton" name="deleteTagNameButton">
|
||||
<Properties>
|
||||
<Property name="icon" type="javax.swing.Icon" editor="org.netbeans.modules.form.editors2.IconEditor">
|
||||
<Image iconType="3" name="/org/sleuthkit/autopsy/images/delete-tag.png"/>
|
||||
</Property>
|
||||
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/casemodule/services/Bundle.properties" key="TagOptionsPanel.deleteTagNameButton.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
<Events>
|
||||
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="deleteTagNameButtonActionPerformed"/>
|
||||
</Events>
|
||||
</Component>
|
||||
</SubComponents>
|
||||
</Container>
|
||||
<Component class="javax.swing.JButton" name="newTagNameButton">
|
||||
<Properties>
|
||||
<Property name="icon" type="javax.swing.Icon" editor="org.netbeans.modules.form.editors2.IconEditor">
|
||||
<Image iconType="3" name="/org/sleuthkit/autopsy/images/add-tag.png"/>
|
||||
</Property>
|
||||
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/casemodule/services/Bundle.properties" key="TagOptionsPanel.newTagNameButton.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
<Events>
|
||||
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="newTagNameButtonActionPerformed"/>
|
||||
</Events>
|
||||
</Component>
|
||||
<Component class="javax.swing.JButton" name="deleteTagNameButton">
|
||||
<Properties>
|
||||
<Property name="icon" type="javax.swing.Icon" editor="org.netbeans.modules.form.editors2.IconEditor">
|
||||
<Image iconType="3" name="/org/sleuthkit/autopsy/images/delete-tag.png"/>
|
||||
</Property>
|
||||
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/casemodule/services/Bundle.properties" key="TagOptionsPanel.deleteTagNameButton.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
<Events>
|
||||
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="deleteTagNameButtonActionPerformed"/>
|
||||
</Events>
|
||||
</Component>
|
||||
</SubComponents>
|
||||
</Container>
|
||||
<Container class="javax.swing.JPanel" name="tagTypesAdditionalPanel">
|
||||
<Constraints>
|
||||
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.support.JSplitPaneSupportLayout" value="org.netbeans.modules.form.compat2.layouts.support.JSplitPaneSupportLayout$JSplitPaneConstraintsDescription">
|
||||
<JSplitPaneConstraints position="right"/>
|
||||
</Constraint>
|
||||
</Constraints>
|
||||
<Container class="javax.swing.JPanel" name="tagTypesAdditionalPanel">
|
||||
<Constraints>
|
||||
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.support.JSplitPaneSupportLayout" value="org.netbeans.modules.form.compat2.layouts.support.JSplitPaneSupportLayout$JSplitPaneConstraintsDescription">
|
||||
<JSplitPaneConstraints position="right"/>
|
||||
</Constraint>
|
||||
</Constraints>
|
||||
|
||||
<Layout>
|
||||
<DimensionLayout dim="0">
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<EmptySpace min="0" pref="356" max="32767" attributes="0"/>
|
||||
</Group>
|
||||
</DimensionLayout>
|
||||
<DimensionLayout dim="1">
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<EmptySpace min="0" pref="456" max="32767" attributes="0"/>
|
||||
</Group>
|
||||
</DimensionLayout>
|
||||
</Layout>
|
||||
<Layout>
|
||||
<DimensionLayout dim="0">
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<EmptySpace min="0" pref="354" max="32767" attributes="0"/>
|
||||
</Group>
|
||||
</DimensionLayout>
|
||||
<DimensionLayout dim="1">
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<EmptySpace min="0" pref="454" max="32767" attributes="0"/>
|
||||
</Group>
|
||||
</DimensionLayout>
|
||||
</Layout>
|
||||
</Container>
|
||||
</SubComponents>
|
||||
</Container>
|
||||
</SubComponents>
|
||||
</Container>
|
||||
|
@ -67,6 +67,7 @@ final class TagOptionsPanel extends javax.swing.JPanel implements OptionsPanel {
|
||||
|
||||
jPanel1 = new javax.swing.JPanel();
|
||||
panelDescriptionLabel = new javax.swing.JLabel();
|
||||
jScrollPane2 = new javax.swing.JScrollPane();
|
||||
jSplitPane1 = new javax.swing.JSplitPane();
|
||||
modifyTagTypesListPanel = new javax.swing.JPanel();
|
||||
tagTypesListLabel = new javax.swing.JLabel();
|
||||
@ -111,13 +112,13 @@ final class TagOptionsPanel extends javax.swing.JPanel implements OptionsPanel {
|
||||
.addGroup(modifyTagTypesListPanelLayout.createSequentialGroup()
|
||||
.addContainerGap()
|
||||
.addGroup(modifyTagTypesListPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
.addComponent(jScrollPane1, javax.swing.GroupLayout.Alignment.TRAILING)
|
||||
.addComponent(tagTypesListLabel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
|
||||
.addGroup(modifyTagTypesListPanelLayout.createSequentialGroup()
|
||||
.addComponent(newTagNameButton)
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||
.addComponent(deleteTagNameButton)
|
||||
.addGap(0, 113, Short.MAX_VALUE))
|
||||
.addComponent(jScrollPane1))
|
||||
.addGap(0, 113, Short.MAX_VALUE)))
|
||||
.addContainerGap())
|
||||
);
|
||||
modifyTagTypesListPanelLayout.setVerticalGroup(
|
||||
@ -126,7 +127,7 @@ final class TagOptionsPanel extends javax.swing.JPanel implements OptionsPanel {
|
||||
.addContainerGap()
|
||||
.addComponent(tagTypesListLabel)
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||
.addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 383, Short.MAX_VALUE)
|
||||
.addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 381, Short.MAX_VALUE)
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||
.addGroup(modifyTagTypesListPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
|
||||
.addComponent(newTagNameButton)
|
||||
@ -140,24 +141,26 @@ final class TagOptionsPanel extends javax.swing.JPanel implements OptionsPanel {
|
||||
tagTypesAdditionalPanel.setLayout(tagTypesAdditionalPanelLayout);
|
||||
tagTypesAdditionalPanelLayout.setHorizontalGroup(
|
||||
tagTypesAdditionalPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
.addGap(0, 356, Short.MAX_VALUE)
|
||||
.addGap(0, 354, Short.MAX_VALUE)
|
||||
);
|
||||
tagTypesAdditionalPanelLayout.setVerticalGroup(
|
||||
tagTypesAdditionalPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
.addGap(0, 456, Short.MAX_VALUE)
|
||||
.addGap(0, 454, Short.MAX_VALUE)
|
||||
);
|
||||
|
||||
jSplitPane1.setRightComponent(tagTypesAdditionalPanel);
|
||||
|
||||
jScrollPane2.setViewportView(jSplitPane1);
|
||||
|
||||
javax.swing.GroupLayout jPanel1Layout = new javax.swing.GroupLayout(jPanel1);
|
||||
jPanel1.setLayout(jPanel1Layout);
|
||||
jPanel1Layout.setHorizontalGroup(
|
||||
jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
.addGroup(javax.swing.GroupLayout.Alignment.TRAILING, jPanel1Layout.createSequentialGroup()
|
||||
.addGroup(jPanel1Layout.createSequentialGroup()
|
||||
.addContainerGap()
|
||||
.addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING)
|
||||
.addComponent(jSplitPane1)
|
||||
.addComponent(panelDescriptionLabel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
|
||||
.addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
.addComponent(panelDescriptionLabel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
|
||||
.addComponent(jScrollPane2))
|
||||
.addContainerGap())
|
||||
);
|
||||
jPanel1Layout.setVerticalGroup(
|
||||
@ -166,7 +169,7 @@ final class TagOptionsPanel extends javax.swing.JPanel implements OptionsPanel {
|
||||
.addContainerGap()
|
||||
.addComponent(panelDescriptionLabel)
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||
.addComponent(jSplitPane1)
|
||||
.addComponent(jScrollPane2, javax.swing.GroupLayout.DEFAULT_SIZE, 458, Short.MAX_VALUE)
|
||||
.addContainerGap())
|
||||
);
|
||||
|
||||
@ -178,9 +181,7 @@ final class TagOptionsPanel extends javax.swing.JPanel implements OptionsPanel {
|
||||
);
|
||||
layout.setVerticalGroup(
|
||||
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
.addGroup(layout.createSequentialGroup()
|
||||
.addComponent(jPanel1, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
|
||||
.addGap(0, 0, Short.MAX_VALUE))
|
||||
.addComponent(jPanel1, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
|
||||
);
|
||||
}// </editor-fold>//GEN-END:initComponents
|
||||
|
||||
@ -220,6 +221,7 @@ final class TagOptionsPanel extends javax.swing.JPanel implements OptionsPanel {
|
||||
private javax.swing.JButton deleteTagNameButton;
|
||||
private javax.swing.JPanel jPanel1;
|
||||
private javax.swing.JScrollPane jScrollPane1;
|
||||
private javax.swing.JScrollPane jScrollPane2;
|
||||
private javax.swing.JSplitPane jSplitPane1;
|
||||
private javax.swing.JPanel modifyTagTypesListPanel;
|
||||
private javax.swing.JButton newTagNameButton;
|
||||
|
@ -140,7 +140,6 @@ public class Metadata extends javax.swing.JPanel implements DataContentViewer {
|
||||
addRow(sb, NbBundle.getMessage(this.getClass(), "Metadata.tableRowTitle.accessed"), ContentUtils.getStringTime(file.getAtime(), file));
|
||||
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) {
|
||||
@ -149,7 +148,6 @@ public class Metadata extends javax.swing.JPanel implements DataContentViewer {
|
||||
addRow(sb, NbBundle.getMessage(this.getClass(), "Metadata.tableRowTitle.md5"), md5);
|
||||
addRow(sb, NbBundle.getMessage(this.getClass(), "Metadata.tableRowTitle.hashLookupResults"), file.getKnown().toString());
|
||||
|
||||
addRow(sb, NbBundle.getMessage(this.getClass(), "Metadata.tableRowTitle.internalid"), Long.toString(file.getId()));
|
||||
if (file.getType().compareTo(TSK_DB_FILES_TYPE_ENUM.LOCAL) == 0) {
|
||||
addRow(sb, NbBundle.getMessage(this.getClass(), "Metadata.tableRowTitle.localPath"), file.getLocalAbsPath());
|
||||
}
|
||||
|
@ -64,12 +64,54 @@ public class Installer extends ModuleInstall {
|
||||
//Note: if shipping with a different CRT version, this will only print a warning
|
||||
//and try to use linker mechanism to find the correct versions of libs.
|
||||
//We should update this if we officially switch to a new version of CRT/compiler
|
||||
System.loadLibrary("msvcr100"); //NON-NLS
|
||||
System.loadLibrary("msvcp100"); //NON-NLS
|
||||
System.loadLibrary("api-ms-win-core-console-l1-1-0"); //NON-NLS
|
||||
System.loadLibrary("api-ms-win-core-datetime-l1-1-0"); //NON-NLS
|
||||
System.loadLibrary("api-ms-win-core-debug-l1-1-0"); //NON-NLS
|
||||
System.loadLibrary("api-ms-win-core-errorhandling-l1-1-0"); //NON-NLS
|
||||
System.loadLibrary("api-ms-win-core-file-l1-1-0"); //NON-NLS
|
||||
System.loadLibrary("api-ms-win-core-file-l1-2-0"); //NON-NLS
|
||||
System.loadLibrary("api-ms-win-core-file-l2-1-0"); //NON-NLS
|
||||
System.loadLibrary("api-ms-win-core-handle-l1-1-0"); //NON-NLS
|
||||
System.loadLibrary("api-ms-win-core-heap-l1-1-0"); //NON-NLS
|
||||
System.loadLibrary("api-ms-win-core-interlocked-l1-1-0"); //NON-NLS
|
||||
System.loadLibrary("api-ms-win-core-libraryloader-l1-1-0"); //NON-NLS
|
||||
System.loadLibrary("api-ms-win-core-localization-l1-2-0"); //NON-NLS
|
||||
System.loadLibrary("api-ms-win-core-memory-l1-1-0"); //NON-NLS
|
||||
System.loadLibrary("api-ms-win-core-namedpipe-l1-1-0"); //NON-NLS
|
||||
System.loadLibrary("api-ms-win-core-processenvironment-l1-1-0"); //NON-NLS
|
||||
System.loadLibrary("api-ms-win-core-processthreads-l1-1-0"); //NON-NLS
|
||||
System.loadLibrary("api-ms-win-core-processthreads-l1-1-1"); //NON-NLS
|
||||
System.loadLibrary("api-ms-win-core-profile-l1-1-0"); //NON-NLS
|
||||
System.loadLibrary("api-ms-win-core-rtlsupport-l1-1-0"); //NON-NLS
|
||||
System.loadLibrary("api-ms-win-core-string-l1-1-0"); //NON-NLS
|
||||
System.loadLibrary("api-ms-win-core-synch-l1-1-0"); //NON-NLS
|
||||
System.loadLibrary("api-ms-win-core-synch-l1-2-0"); //NON-NLS
|
||||
System.loadLibrary("api-ms-win-core-sysinfo-l1-1-0"); //NON-NLS
|
||||
System.loadLibrary("api-ms-win-core-timezone-l1-1-0"); //NON-NLS
|
||||
System.loadLibrary("api-ms-win-core-util-l1-1-0"); //NON-NLS
|
||||
System.loadLibrary("api-ms-win-crt-conio-l1-1-0"); //NON-NLS
|
||||
System.loadLibrary("api-ms-win-crt-convert-l1-1-0"); //NON-NLS
|
||||
System.loadLibrary("api-ms-win-crt-environment-l1-1-0"); //NON-NLS
|
||||
System.loadLibrary("api-ms-win-crt-filesystem-l1-1-0"); //NON-NLS
|
||||
System.loadLibrary("api-ms-win-crt-heap-l1-1-0"); //NON-NLS
|
||||
System.loadLibrary("api-ms-win-crt-locale-l1-1-0"); //NON-NLS
|
||||
System.loadLibrary("api-ms-win-crt-math-l1-1-0"); //NON-NLS
|
||||
System.loadLibrary("api-ms-win-crt-multibyte-l1-1-0"); //NON-NLS
|
||||
System.loadLibrary("api-ms-win-crt-private-l1-1-0"); //NON-NLS
|
||||
System.loadLibrary("api-ms-win-crt-process-l1-1-0"); //NON-NLS
|
||||
System.loadLibrary("api-ms-win-crt-runtime-l1-1-0"); //NON-NLS
|
||||
System.loadLibrary("api-ms-win-crt-stdio-l1-1-0"); //NON-NLS
|
||||
System.loadLibrary("api-ms-win-crt-string-l1-1-0"); //NON-NLS
|
||||
System.loadLibrary("api-ms-win-crt-time-l1-1-0"); //NON-NLS
|
||||
System.loadLibrary("api-ms-win-crt-utility-l1-1-0"); //NON-NLS
|
||||
|
||||
logger.log(Level.INFO, "MSVCR100 and MSVCP100 libraries loaded"); //NON-NLS
|
||||
System.loadLibrary("ucrtbase"); //NON-NLS
|
||||
System.loadLibrary("vcruntime140"); //NON-NLS
|
||||
System.loadLibrary("msvcp140"); //NON-NLS
|
||||
|
||||
logger.log(Level.INFO, "Visual C Runtime libraries loaded"); //NON-NLS
|
||||
} catch (UnsatisfiedLinkError e) {
|
||||
logger.log(Level.SEVERE, "Error loading MSVCR100 and MSVCP100 libraries, ", e); //NON-NLS
|
||||
logger.log(Level.SEVERE, "Error loading Visual C Runtime libraries, ", e); //NON-NLS
|
||||
}
|
||||
|
||||
try {
|
||||
|
@ -34,7 +34,6 @@ import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.TreeMap;
|
||||
import java.util.logging.Level;
|
||||
import javax.swing.JTable;
|
||||
import javax.swing.ListSelectionModel;
|
||||
import javax.swing.SwingUtilities;
|
||||
@ -56,11 +55,9 @@ import org.openide.nodes.NodeEvent;
|
||||
import org.openide.nodes.NodeListener;
|
||||
import org.openide.nodes.NodeMemberEvent;
|
||||
import org.openide.nodes.NodeReorderEvent;
|
||||
import org.openide.nodes.Sheet;
|
||||
import org.openide.util.NbBundle;
|
||||
import org.openide.util.NbPreferences;
|
||||
import org.sleuthkit.autopsy.corecomponentinterfaces.DataResultViewer;
|
||||
import org.sleuthkit.autopsy.coreutils.Logger;
|
||||
|
||||
/**
|
||||
* DataResult sortable table viewer
|
||||
@ -80,10 +77,10 @@ public class DataResultViewerTable extends AbstractDataResultViewer {
|
||||
private static final String DUMMY_NODE_DISPLAY_NAME = NbBundle.getMessage(DataResultViewerTable.class, "DataResultViewerTable.dummyNodeDisplayName");
|
||||
private static final Color TAGGED_COLOR = new Color(230, 235, 240);
|
||||
private Node currentRoot;
|
||||
// The following two variables keep track of whether the user is trying
|
||||
// to move the first column, which is not allowed.
|
||||
private int oldColumnIndex = -1;
|
||||
private int newColumnIndex = -1;
|
||||
// When a column in the table is moved, these two variables keep track of where
|
||||
// the column started and where it ended up.
|
||||
private int startColumnIndex = -1;
|
||||
private int endColumnIndex = -1;
|
||||
|
||||
/**
|
||||
* Creates a DataResultViewerTable object that is compatible with node
|
||||
@ -137,11 +134,19 @@ public class DataResultViewerTable extends AbstractDataResultViewer {
|
||||
if (fromIndex == toIndex) {
|
||||
return;
|
||||
}
|
||||
// to keep track of attempts to move the first column
|
||||
if (oldColumnIndex == -1) {
|
||||
oldColumnIndex = fromIndex;
|
||||
|
||||
/* Because a column may be dragged to several different positions before
|
||||
* the mouse is released (thus causing multiple TableColumnModelEvents to
|
||||
* be fired), we want to keep track of the starting column index in this
|
||||
* potential series of movements. Therefore we only keep track of the
|
||||
* original fromIndex in startColumnIndex, but we always update
|
||||
* endColumnIndex to know the final position of the moved column.
|
||||
* See the MouseListener mouseReleased method.
|
||||
*/
|
||||
if (startColumnIndex == -1) {
|
||||
startColumnIndex = fromIndex;
|
||||
}
|
||||
newColumnIndex = toIndex;
|
||||
endColumnIndex = toIndex;
|
||||
|
||||
List<Node.Property<?>> props = new ArrayList<>(propertiesAcc);
|
||||
Node.Property<?> prop = props.remove(fromIndex);
|
||||
@ -158,10 +163,20 @@ public class DataResultViewerTable extends AbstractDataResultViewer {
|
||||
ov.getOutline().getTableHeader().addMouseListener(new MouseAdapter() {
|
||||
@Override
|
||||
public void mouseReleased(MouseEvent e) {
|
||||
if (oldColumnIndex != -1 && (oldColumnIndex == 0 || newColumnIndex == 0)) {
|
||||
ov.getOutline().moveColumn(newColumnIndex, oldColumnIndex);
|
||||
/* If the startColumnIndex is not -1 (which is the reset value), that
|
||||
* means columns have been moved around. We then check to see if either
|
||||
* the starting or end position is 0 (the first column), and then swap
|
||||
* them back if that is the case because we don't want to allow movement
|
||||
* of the first column. We then reset startColumnIndex to -1, the reset
|
||||
* value.
|
||||
* We check if startColumnIndex is at reset or not because it is
|
||||
* possible for the mouse to be released and a MouseEvent to be fired
|
||||
* without having moved any columns.
|
||||
*/
|
||||
if (startColumnIndex != -1 && (startColumnIndex == 0 || endColumnIndex == 0)) {
|
||||
ov.getOutline().moveColumn(endColumnIndex, startColumnIndex);
|
||||
}
|
||||
oldColumnIndex = -1;
|
||||
startColumnIndex = -1;
|
||||
}
|
||||
});
|
||||
}
|
||||
@ -217,68 +232,6 @@ public class DataResultViewerTable extends AbstractDataResultViewer {
|
||||
private javax.swing.JScrollPane tableScrollPanel;
|
||||
// End of variables declaration//GEN-END:variables
|
||||
|
||||
/**
|
||||
* Gets regular Bean property set properties from first child of Node.
|
||||
*
|
||||
* @param parent Node with at least one child to get properties from
|
||||
*
|
||||
* @return Properties,
|
||||
*/
|
||||
private Node.Property<?>[] getChildPropertyHeaders(Node parent) {
|
||||
Node firstChild = parent.getChildren().getNodeAt(0);
|
||||
|
||||
if (firstChild == null) {
|
||||
throw new IllegalArgumentException(
|
||||
NbBundle.getMessage(this.getClass(), "DataResultViewerTable.illegalArgExc.noChildFromParent"));
|
||||
} else {
|
||||
for (PropertySet ps : firstChild.getPropertySets()) {
|
||||
if (ps.getName().equals(Sheet.PROPERTIES)) {
|
||||
return ps.getProperties();
|
||||
}
|
||||
}
|
||||
|
||||
throw new IllegalArgumentException(
|
||||
NbBundle.getMessage(this.getClass(), "DataResultViewerTable.illegalArgExc.childWithoutPropertySet"));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets regular Bean property set properties from all first children and,
|
||||
* recursively, subchildren of Node. Note: won't work out the box for lazy
|
||||
* load - you need to set all children props for the parent by hand
|
||||
*
|
||||
* @param parent Node with at least one child to get properties from
|
||||
*
|
||||
* @return Properties,
|
||||
*/
|
||||
@SuppressWarnings("rawtypes")
|
||||
private Node.Property[] getAllChildPropertyHeaders(Node parent) {
|
||||
Node firstChild = parent.getChildren().getNodeAt(0);
|
||||
|
||||
Property[] properties = null;
|
||||
|
||||
if (firstChild == null) {
|
||||
throw new IllegalArgumentException(
|
||||
NbBundle.getMessage(this.getClass(), "DataResultViewerTable.illegalArgExc.noChildFromParent"));
|
||||
} else {
|
||||
Set<Property> allProperties = new LinkedHashSet<>();
|
||||
while (firstChild != null) {
|
||||
for (PropertySet ps : firstChild.getPropertySets()) {
|
||||
final Property[] props = ps.getProperties();
|
||||
final int propsNum = props.length;
|
||||
for (int i = 0; i < propsNum; ++i) {
|
||||
allProperties.add(props[i]);
|
||||
}
|
||||
}
|
||||
firstChild = firstChild.getChildren().getNodeAt(0);
|
||||
}
|
||||
|
||||
properties = allProperties.toArray(new Property<?>[0]);
|
||||
}
|
||||
return properties;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets regular Bean property set properties from all children and,
|
||||
* recursively, subchildren of Node. Note: won't work out the box for lazy
|
||||
@ -320,6 +273,11 @@ public class DataResultViewerTable extends AbstractDataResultViewer {
|
||||
@Override
|
||||
public void setNode(Node selectedNode) {
|
||||
final OutlineView ov = ((OutlineView) this.tableScrollPanel);
|
||||
/* The quick filter must be reset because when determining column width,
|
||||
* ETable.getRowCount is called, and the documentation states that quick
|
||||
* filters must be unset for the method to work
|
||||
* "If the quick-filter is applied the number of rows do not match the number of rows in the model."
|
||||
*/
|
||||
ov.getOutline().unsetQuickFilter();
|
||||
// change the cursor to "waiting cursor" for this operation
|
||||
this.setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
|
||||
@ -405,9 +363,7 @@ public class DataResultViewerTable extends AbstractDataResultViewer {
|
||||
// Just let the table resize itself.
|
||||
ov.getOutline().setAutoResizeMode((props.size() > 0) ? JTable.AUTO_RESIZE_OFF : JTable.AUTO_RESIZE_ALL_COLUMNS);
|
||||
|
||||
// get first row's values for the table
|
||||
if (root.getChildren().getNodesCount() != 0) {
|
||||
|
||||
final Graphics graphics = ov.getGraphics();
|
||||
if (graphics != null) {
|
||||
final FontMetrics metrics = graphics.getFontMetrics();
|
||||
@ -420,9 +376,8 @@ public class DataResultViewerTable extends AbstractDataResultViewer {
|
||||
int columnWidthLimit = (column == 0) ? 350 : 300;
|
||||
int valuesWidth = 0;
|
||||
|
||||
// find the maximum width needed to fit the values for the first 15 rows, at most
|
||||
// *15 is an arbitrary number
|
||||
for (int row = 0; row < Math.min(15, ov.getOutline().getRowCount()); row++) {
|
||||
// find the maximum width needed to fit the values for the first 100 rows, at most
|
||||
for (int row = 0; row < Math.min(100, ov.getOutline().getRowCount()); row++) {
|
||||
TableCellRenderer renderer = ov.getOutline().getCellRenderer(row, column);
|
||||
Component comp = ov.getOutline().prepareRenderer(renderer, row, column);
|
||||
valuesWidth = Math.max(comp.getPreferredSize().width, valuesWidth);
|
||||
@ -438,51 +393,52 @@ public class DataResultViewerTable extends AbstractDataResultViewer {
|
||||
ov.getOutline().getColumnModel().getColumn(column).setPreferredWidth(columnWidth);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// if there's no content just auto resize all columns
|
||||
ov.getOutline().setAutoResizeMode(JTable.AUTO_RESIZE_ALL_COLUMNS);
|
||||
}
|
||||
|
||||
/**
|
||||
* This custom renderer extends the renderer that was already being
|
||||
* used by the outline table. This renderer colors a row if the
|
||||
* tags property of the node is not empty.
|
||||
*/
|
||||
class ColorTagCustomRenderer extends DefaultOutlineCellRenderer {
|
||||
private static final long serialVersionUID = 1L;
|
||||
@Override
|
||||
public Component getTableCellRendererComponent(JTable table,
|
||||
Object value, boolean isSelected, boolean hasFocus, int row, int col) {
|
||||
|
||||
Component component = super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, col);
|
||||
// only override the color if a node is not selected
|
||||
if (!isSelected) {
|
||||
Node node = currentRoot.getChildren().getNodeAt(table.convertRowIndexToModel(row));
|
||||
boolean tagFound = false;
|
||||
if (node != null) {
|
||||
Node.PropertySet[] propSets = node.getPropertySets();
|
||||
if (propSets.length != 0) {
|
||||
// currently, a node has only one property set, named Sheet.PROPERTIES ("properties")
|
||||
Node.Property<?>[] props = propSets[0].getProperties();
|
||||
for (Property<?> prop : props) {
|
||||
if (prop.getName().equals("Tags")) {
|
||||
try {
|
||||
tagFound = !prop.getValue().equals("");
|
||||
} catch (IllegalAccessException | InvocationTargetException ignore) {
|
||||
}
|
||||
break;
|
||||
/**
|
||||
* This custom renderer extends the renderer that was already being
|
||||
* used by the outline table. This renderer colors a row if the
|
||||
* tags property of the node is not empty.
|
||||
*/
|
||||
class ColorTagCustomRenderer extends DefaultOutlineCellRenderer {
|
||||
private static final long serialVersionUID = 1L;
|
||||
@Override
|
||||
public Component getTableCellRendererComponent(JTable table,
|
||||
Object value, boolean isSelected, boolean hasFocus, int row, int col) {
|
||||
|
||||
Component component = super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, col);
|
||||
// only override the color if a node is not selected
|
||||
if (!isSelected) {
|
||||
Node node = currentRoot.getChildren().getNodeAt(table.convertRowIndexToModel(row));
|
||||
boolean tagFound = false;
|
||||
if (node != null) {
|
||||
Node.PropertySet[] propSets = node.getPropertySets();
|
||||
if (propSets.length != 0) {
|
||||
// currently, a node has only one property set, named Sheet.PROPERTIES ("properties")
|
||||
Node.Property<?>[] props = propSets[0].getProperties();
|
||||
for (Property<?> prop : props) {
|
||||
if (prop.getName().equals("Tags")) {
|
||||
try {
|
||||
tagFound = !prop.getValue().equals("");
|
||||
} catch (IllegalAccessException | InvocationTargetException ignore) {
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
//if the node does have associated tags, set its background color
|
||||
if (tagFound) {
|
||||
component.setBackground(TAGGED_COLOR);
|
||||
}
|
||||
}
|
||||
return component;
|
||||
//if the node does have associated tags, set its background color
|
||||
if (tagFound) {
|
||||
component.setBackground(TAGGED_COLOR);
|
||||
}
|
||||
}
|
||||
return component;
|
||||
}
|
||||
ov.getOutline().setDefaultRenderer(Object.class, new ColorTagCustomRenderer());
|
||||
} else {
|
||||
ov.getOutline().setAutoResizeMode(JTable.AUTO_RESIZE_ALL_COLUMNS);
|
||||
}
|
||||
ov.getOutline().setDefaultRenderer(Object.class, new ColorTagCustomRenderer());
|
||||
}
|
||||
|
||||
/**
|
||||
@ -504,7 +460,7 @@ public class DataResultViewerTable extends AbstractDataResultViewer {
|
||||
List<Node.Property<?>> props = new ArrayList<>(propertiesAcc);
|
||||
for (int i = 0; i < props.size(); i++) {
|
||||
Property<?> prop = props.get(i);
|
||||
NbPreferences.forModule(this.getClass()).put(getPreferenceKey(prop, tfn.getItemType()), String.valueOf(i));
|
||||
NbPreferences.forModule(this.getClass()).put(getColumnPreferenceKey(prop, tfn.getColumnOrderKey()), String.valueOf(i));
|
||||
}
|
||||
}
|
||||
|
||||
@ -523,8 +479,7 @@ public class DataResultViewerTable extends AbstractDataResultViewer {
|
||||
if (currentRoot instanceof TableFilterNode) {
|
||||
tfn = (TableFilterNode) currentRoot;
|
||||
} else {
|
||||
Logger.getLogger(DataResultViewerTable.class.getName()).log(Level.INFO,
|
||||
"Node {0} is not a TableFilterNode, columns are going to be in default order", currentRoot.getName());
|
||||
// The node is not a TableFilterNode, columns are going to be in default order
|
||||
return props;
|
||||
}
|
||||
|
||||
@ -535,8 +490,8 @@ public class DataResultViewerTable extends AbstractDataResultViewer {
|
||||
Map<Integer, Node.Property<?>> propsFromPreferences = new TreeMap<>();
|
||||
int offset = props.size();
|
||||
for (Property<?> prop : props) {
|
||||
Integer value = Integer.valueOf(NbPreferences.forModule(this.getClass()).get(getPreferenceKey(prop, tfn.getItemType()), "-1"));
|
||||
if (value >= 0) {
|
||||
Integer value = Integer.valueOf(NbPreferences.forModule(this.getClass()).get(getColumnPreferenceKey(prop, tfn.getColumnOrderKey()), "-1"));
|
||||
if (value >= 0 && value < offset) {
|
||||
propsFromPreferences.put(value, prop);
|
||||
} else {
|
||||
propsFromPreferences.put(offset, prop);
|
||||
@ -559,7 +514,7 @@ public class DataResultViewerTable extends AbstractDataResultViewer {
|
||||
* @param type The type of the current node
|
||||
* @return A generated key for the preference file
|
||||
*/
|
||||
private String getPreferenceKey(Property<?> prop, String type) {
|
||||
private String getColumnPreferenceKey(Property<?> prop, String type) {
|
||||
return type.replaceAll("[^a-zA-Z0-9_]", "") + "."
|
||||
+ prop.getName().replaceAll("[^a-zA-Z0-9_]", "") + ".column";
|
||||
}
|
||||
|
@ -25,11 +25,13 @@ import org.openide.util.NbBundle;
|
||||
/**
|
||||
* A filter node that creates at most one layer of child nodes for the node it
|
||||
* wraps. It is designed to be used for nodes displayed in Autopsy table views.
|
||||
* This ensures that the table view for the node will not recursively display
|
||||
* child nodes and display only the first layer of child nodes.
|
||||
*/
|
||||
public class TableFilterNode extends FilterNode {
|
||||
|
||||
private final boolean createChildren;
|
||||
private String itemType = "NONE";
|
||||
private String columnOrderKey = "NONE";
|
||||
|
||||
/**
|
||||
* Constructs a filter node that creates at most one layer of child nodes
|
||||
@ -39,6 +41,7 @@ public class TableFilterNode extends FilterNode {
|
||||
* @param wrappedNode The node to wrap in the filter node.
|
||||
* @param createChildren True if a children (child factory) object should be
|
||||
* created for the wrapped node.
|
||||
* The constructor should include column order key. (See getColumnOrderKey)
|
||||
*/
|
||||
public TableFilterNode(Node wrappedNode, boolean createChildren) {
|
||||
super(wrappedNode, TableFilterChildren.createInstance(wrappedNode, createChildren));
|
||||
@ -51,13 +54,14 @@ public class TableFilterNode extends FilterNode {
|
||||
* @param wrappedNode The node to wrap in the filter node.
|
||||
* @param createChildren True if a children (child factory) object should be
|
||||
* created for the wrapped node.
|
||||
* @param itemType A name of the node, based on its class name and
|
||||
* filter or artifact type if it holds those.
|
||||
* @param columnOrderKey A key that represents the type of the original
|
||||
* wrapped node and what is being displayed under that
|
||||
* node.
|
||||
*/
|
||||
public TableFilterNode(Node wrappedNode, boolean createChildren, String itemType) {
|
||||
public TableFilterNode(Node wrappedNode, boolean createChildren, String columnOrderKey) {
|
||||
super(wrappedNode, TableFilterChildren.createInstance(wrappedNode, createChildren));
|
||||
this.createChildren = createChildren;
|
||||
this.itemType = itemType;
|
||||
this.columnOrderKey = columnOrderKey;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -76,10 +80,13 @@ public class TableFilterNode extends FilterNode {
|
||||
}
|
||||
|
||||
/**
|
||||
* @return itemType of associated DisplayableItemNode to allow for custom
|
||||
* column orderings in the DataResultViewerTable
|
||||
* @return the column order key, which allows custom column ordering to be
|
||||
* written into a properties file and be reloaded for future use in
|
||||
* a table with the same root node or for different cases. This is
|
||||
* done by DataResultViewerTable. The key should represent what
|
||||
* kinds of items the table is showing.
|
||||
*/
|
||||
String getItemType() {
|
||||
return itemType;
|
||||
String getColumnOrderKey() {
|
||||
return columnOrderKey;
|
||||
}
|
||||
}
|
||||
|
@ -130,14 +130,6 @@ public class ArtifactStringContent implements StringContent {
|
||||
buffer.append("</td>"); //NON-NLS
|
||||
buffer.append("</tr>\n"); //NON-NLS
|
||||
|
||||
// add artifact ID (useful for debugging)
|
||||
buffer.append("<tr><td>"); //NON-NLS
|
||||
buffer.append(NbBundle.getMessage(this.getClass(), "ArtifactStringContent.getStr.artifactId.text"));
|
||||
buffer.append("</td><td>"); //NON-NLS
|
||||
buffer.append(artifact.getArtifactID());
|
||||
buffer.append("</td>"); //NON-NLS
|
||||
buffer.append("</tr>\n"); //NON-NLS
|
||||
|
||||
buffer.append("</table>"); //NON-NLS
|
||||
buffer.append("</html>\n"); //NON-NLS
|
||||
|
||||
|
@ -18,8 +18,6 @@
|
||||
*/
|
||||
package org.sleuthkit.autopsy.datamodel.accounts;
|
||||
|
||||
import org.sleuthkit.autopsy.datamodel.AutopsyItemVisitor;
|
||||
import org.sleuthkit.autopsy.datamodel.AutopsyVisitableItem;
|
||||
import com.google.common.collect.Range;
|
||||
import com.google.common.collect.RangeMap;
|
||||
import com.google.common.collect.TreeRangeMap;
|
||||
@ -59,6 +57,8 @@ import org.openide.util.Utilities;
|
||||
import org.openide.util.lookup.Lookups;
|
||||
import org.sleuthkit.autopsy.casemodule.Case;
|
||||
import org.sleuthkit.autopsy.corecomponents.DataResultTopComponent;
|
||||
import org.sleuthkit.autopsy.datamodel.AutopsyItemVisitor;
|
||||
import org.sleuthkit.autopsy.datamodel.AutopsyVisitableItem;
|
||||
import org.sleuthkit.autopsy.datamodel.BlackboardArtifactNode;
|
||||
import org.sleuthkit.autopsy.datamodel.CreditCards;
|
||||
import org.sleuthkit.autopsy.datamodel.DataModelActionsFactory;
|
||||
@ -76,6 +76,7 @@ import org.sleuthkit.datamodel.BlackboardAttribute;
|
||||
import org.sleuthkit.datamodel.Content;
|
||||
import org.sleuthkit.datamodel.SleuthkitCase;
|
||||
import org.sleuthkit.datamodel.TskCoreException;
|
||||
import org.sleuthkit.datamodel.TskData.DbType;
|
||||
|
||||
/**
|
||||
* AutopsyVisitableItem for the Accounts section of the tree. All nodes,
|
||||
@ -146,6 +147,14 @@ final public class Accounts implements AutopsyVisitableItem {
|
||||
*/
|
||||
private abstract class ObservingChildren<X> extends Children.Keys<X> {
|
||||
|
||||
/**
|
||||
* Override of default constructor to force lazy creation of nodes, by
|
||||
* concrete instances of ObservingChildren
|
||||
*/
|
||||
ObservingChildren() {
|
||||
super(true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create of keys used by this Children object to represent the child
|
||||
* nodes.
|
||||
@ -167,6 +176,9 @@ final public class Accounts implements AutopsyVisitableItem {
|
||||
@Subscribe
|
||||
abstract void handleReviewStatusChange(ReviewStatusChangeEvent event);
|
||||
|
||||
@Subscribe
|
||||
abstract void handleDataAdded(ModuleDataEvent event);
|
||||
|
||||
@Override
|
||||
protected void removeNotify() {
|
||||
super.removeNotify();
|
||||
@ -219,7 +231,7 @@ final public class Accounts implements AutopsyVisitableItem {
|
||||
ModuleDataEvent eventData = (ModuleDataEvent) evt.getOldValue();
|
||||
if (null != eventData
|
||||
&& eventData.getBlackboardArtifactType().getTypeID() == ARTIFACT_TYPE.TSK_ACCOUNT.getTypeID()) {
|
||||
refreshKeys();
|
||||
reviewStatusBus.post(eventData);
|
||||
}
|
||||
} catch (IllegalStateException notUsed) {
|
||||
// Case is closed, do nothing.
|
||||
@ -250,7 +262,13 @@ final public class Accounts implements AutopsyVisitableItem {
|
||||
|
||||
@Subscribe
|
||||
@Override
|
||||
public void handleReviewStatusChange(ReviewStatusChangeEvent event) {
|
||||
void handleReviewStatusChange(ReviewStatusChangeEvent event) {
|
||||
refreshKeys();
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
@Override
|
||||
void handleDataAdded(ModuleDataEvent event) {
|
||||
refreshKeys();
|
||||
}
|
||||
|
||||
@ -377,10 +395,17 @@ final public class Accounts implements AutopsyVisitableItem {
|
||||
}
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
@Override
|
||||
void handleReviewStatusChange(ReviewStatusChangeEvent event) {
|
||||
refreshKeys();
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
@Override
|
||||
void handleDataAdded(ModuleDataEvent event) {
|
||||
refreshKeys();
|
||||
}
|
||||
}
|
||||
|
||||
private DefaultAccountTypeNode(String accountTypeName) {
|
||||
@ -426,10 +451,12 @@ final public class Accounts implements AutopsyVisitableItem {
|
||||
*/
|
||||
final private class ViewModeFactory extends ObservingChildren<CreditCardViewMode> {
|
||||
|
||||
@Subscribe
|
||||
@Override
|
||||
public void handleReviewStatusChange(ReviewStatusChangeEvent event) {
|
||||
refreshKeys();
|
||||
void handleReviewStatusChange(ReviewStatusChangeEvent event) {
|
||||
}
|
||||
|
||||
@Override
|
||||
void handleDataAdded(ModuleDataEvent event) {
|
||||
}
|
||||
|
||||
/**
|
||||
@ -490,7 +517,13 @@ final public class Accounts implements AutopsyVisitableItem {
|
||||
|
||||
@Subscribe
|
||||
@Override
|
||||
public void handleReviewStatusChange(ReviewStatusChangeEvent event) {
|
||||
void handleReviewStatusChange(ReviewStatusChangeEvent event) {
|
||||
refreshKeys();
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
@Override
|
||||
void handleDataAdded(ModuleDataEvent event) {
|
||||
refreshKeys();
|
||||
}
|
||||
|
||||
@ -499,10 +532,15 @@ final public class Accounts implements AutopsyVisitableItem {
|
||||
List<FileWithCCN> list = new ArrayList<>();
|
||||
String query
|
||||
= "SELECT blackboard_artifacts.obj_id," //NON-NLS
|
||||
+ " solr_attribute.value_text AS solr_document_id, " //NON-NLS
|
||||
+ " GROUP_CONCAT(blackboard_artifacts.artifact_id) AS artifact_IDs, " //NON-NLS
|
||||
+ " COUNT( blackboard_artifacts.artifact_id) AS hits, " //NON-NLS
|
||||
+ " GROUP_CONCAT(blackboard_artifacts.review_status_id) AS review_status_ids "
|
||||
+ " solr_attribute.value_text AS solr_document_id, "; //NON-NLS
|
||||
if(skCase.getDatabaseType().equals(DbType.POSTGRESQL)){
|
||||
query += " string_agg(blackboard_artifacts.artifact_id::character varying, ',') AS artifact_IDs, " //NON-NLS
|
||||
+ " string_agg(blackboard_artifacts.review_status_id::character varying, ',') AS review_status_ids, ";
|
||||
} else {
|
||||
query += " GROUP_CONCAT(blackboard_artifacts.artifact_id) AS artifact_IDs, " //NON-NLS
|
||||
+ " GROUP_CONCAT(blackboard_artifacts.review_status_id) AS review_status_ids, ";
|
||||
}
|
||||
query += " COUNT( blackboard_artifacts.artifact_id) AS hits " //NON-NLS
|
||||
+ " FROM blackboard_artifacts " //NON-NLS
|
||||
+ " LEFT JOIN blackboard_attributes as solr_attribute ON blackboard_artifacts.artifact_id = solr_attribute.artifact_id " //NON-NLS
|
||||
+ " AND solr_attribute.attribute_type_id = " + BlackboardAttribute.ATTRIBUTE_TYPE.TSK_KEYWORD_SEARCH_DOCUMENT_ID.getTypeID() //NON-NLS
|
||||
@ -571,11 +609,15 @@ final public class Accounts implements AutopsyVisitableItem {
|
||||
+ " AND account_type.value_text = '" + Account.Type.CREDIT_CARD.name() + "'" //NON-NLS
|
||||
+ " WHERE blackboard_artifacts.artifact_type_id = " + BlackboardArtifact.ARTIFACT_TYPE.TSK_ACCOUNT.getTypeID() //NON-NLS
|
||||
+ getRejectedArtifactFilterClause()
|
||||
+ " GROUP BY blackboard_artifacts.obj_id, solr_attribute.value_text )";
|
||||
+ " GROUP BY blackboard_artifacts.obj_id, solr_attribute.value_text ) AS foo";
|
||||
try (SleuthkitCase.CaseDbQuery results = skCase.executeQuery(query);
|
||||
ResultSet rs = results.getResultSet();) {
|
||||
while (rs.next()) {
|
||||
setDisplayName(Bundle.Accounts_ByFileNode_displayName(rs.getLong("count(*)")));
|
||||
if(skCase.getDatabaseType().equals(DbType.POSTGRESQL)){
|
||||
setDisplayName(Bundle.Accounts_ByFileNode_displayName(rs.getLong("count")));
|
||||
} else {
|
||||
setDisplayName(Bundle.Accounts_ByFileNode_displayName(rs.getLong("count(*)")));
|
||||
}
|
||||
}
|
||||
} catch (TskCoreException | SQLException ex) {
|
||||
LOGGER.log(Level.SEVERE, "Error querying for files with ccn hits.", ex); //NON-NLS
|
||||
@ -599,7 +641,12 @@ final public class Accounts implements AutopsyVisitableItem {
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
public void handleReviewStatusChange(ReviewStatusChangeEvent event) {
|
||||
void handleReviewStatusChange(ReviewStatusChangeEvent event) {
|
||||
updateDisplayName();
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
void handleDataAdded(ModuleDataEvent event) {
|
||||
updateDisplayName();
|
||||
}
|
||||
}
|
||||
@ -617,7 +664,13 @@ final public class Accounts implements AutopsyVisitableItem {
|
||||
|
||||
@Subscribe
|
||||
@Override
|
||||
public void handleReviewStatusChange(ReviewStatusChangeEvent event) {
|
||||
void handleReviewStatusChange(ReviewStatusChangeEvent event) {
|
||||
refreshKeys();
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
@Override
|
||||
void handleDataAdded(ModuleDataEvent event) {
|
||||
refreshKeys();
|
||||
}
|
||||
|
||||
@ -718,7 +771,12 @@ final public class Accounts implements AutopsyVisitableItem {
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
public void handleReviewStatusChange(ReviewStatusChangeEvent event) {
|
||||
void handleReviewStatusChange(ReviewStatusChangeEvent event) {
|
||||
updateDisplayName();
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
void handleDataAdded(ModuleDataEvent event) {
|
||||
updateDisplayName();
|
||||
}
|
||||
}
|
||||
@ -960,15 +1018,18 @@ final public class Accounts implements AutopsyVisitableItem {
|
||||
|
||||
@Subscribe
|
||||
@Override
|
||||
public void handleReviewStatusChange(ReviewStatusChangeEvent event) {
|
||||
void handleReviewStatusChange(ReviewStatusChangeEvent event) {
|
||||
refreshKeys();
|
||||
//make sure to refresh the nodes for artifacts that changed statuses.
|
||||
//make sure to refresh the nodes for artifacts that changed statuses.
|
||||
event.artifacts.stream().map(BlackboardArtifact::getArtifactID).forEach(this::refreshKey);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
@Subscribe
|
||||
@Override
|
||||
void handleDataAdded(ModuleDataEvent event) {
|
||||
refreshKeys();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected List<Long> createKeys() {
|
||||
List<Long> list = new ArrayList<>();
|
||||
@ -979,7 +1040,7 @@ final public class Accounts implements AutopsyVisitableItem {
|
||||
+ " JOIN blackboard_attributes ON blackboard_artifacts.artifact_id = blackboard_attributes.artifact_id " //NON-NLS
|
||||
+ " WHERE blackboard_artifacts.artifact_type_id = " + BlackboardArtifact.ARTIFACT_TYPE.TSK_ACCOUNT.getTypeID() //NON-NLS
|
||||
+ " AND blackboard_attributes.attribute_type_id = " + BlackboardAttribute.ATTRIBUTE_TYPE.TSK_CARD_NUMBER.getTypeID() //NON-NLS
|
||||
+ " AND blackboard_attributes.value_text >= \"" + bin.getBINStart() + "\" AND blackboard_attributes.value_text < \"" + (bin.getBINEnd() + 1) + "\"" //NON-NLS
|
||||
+ " AND blackboard_attributes.value_text >= '" + bin.getBINStart() + "' AND blackboard_attributes.value_text < '" + (bin.getBINEnd() + 1) + "'" //NON-NLS
|
||||
+ getRejectedArtifactFilterClause()
|
||||
+ " ORDER BY blackboard_attributes.value_text"; //NON-NLS
|
||||
try (SleuthkitCase.CaseDbQuery results = skCase.executeQuery(query);
|
||||
@ -1010,12 +1071,11 @@ final public class Accounts implements AutopsyVisitableItem {
|
||||
}
|
||||
}
|
||||
private final BinResult bin;
|
||||
// private final CreditCardNumberFactory accountFactory;
|
||||
|
||||
private BINNode(BinResult bin) {
|
||||
super(Children.LEAF);
|
||||
setChildren(Children.createLazy(CreditCardNumberFactory::new));
|
||||
this.bin = bin;
|
||||
setChildren(Children.createLazy(CreditCardNumberFactory::new));
|
||||
setName(getBinRangeString());
|
||||
updateDisplayName();
|
||||
this.setIconBaseWithExtension("org/sleuthkit/autopsy/images/bank.png"); //NON-NLS
|
||||
@ -1023,7 +1083,12 @@ final public class Accounts implements AutopsyVisitableItem {
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
public void handleReviewStatusChange(ReviewStatusChangeEvent event) {
|
||||
void handleReviewStatusChange(ReviewStatusChangeEvent event) {
|
||||
updateDisplayName();
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
void handleDataAdded(ModuleDataEvent event) {
|
||||
updateDisplayName();
|
||||
}
|
||||
|
||||
@ -1034,7 +1099,7 @@ final public class Accounts implements AutopsyVisitableItem {
|
||||
+ " JOIN blackboard_attributes ON blackboard_artifacts.artifact_id = blackboard_attributes.artifact_id " //NON-NLS
|
||||
+ " WHERE blackboard_artifacts.artifact_type_id = " + BlackboardArtifact.ARTIFACT_TYPE.TSK_ACCOUNT.getTypeID() //NON-NLS
|
||||
+ " AND blackboard_attributes.attribute_type_id = " + BlackboardAttribute.ATTRIBUTE_TYPE.TSK_CARD_NUMBER.getTypeID() //NON-NLS
|
||||
+ " AND blackboard_attributes.value_text >= \"" + bin.getBINStart() + "\" AND blackboard_attributes.value_text < \"" + (bin.getBINEnd() + 1) + "\"" //NON-NLS
|
||||
+ " AND blackboard_attributes.value_text >= '" + bin.getBINStart() + "' AND blackboard_attributes.value_text < '" + (bin.getBINEnd() + 1) + "'" //NON-NLS
|
||||
+ getRejectedArtifactFilterClause();
|
||||
try (SleuthkitCase.CaseDbQuery results = skCase.executeQuery(query);
|
||||
ResultSet rs = results.getResultSet();) {
|
||||
@ -1334,18 +1399,27 @@ final public class Accounts implements AutopsyVisitableItem {
|
||||
*/
|
||||
if (newStatus == BlackboardArtifact.ReviewStatus.REJECTED && showRejected == false) {
|
||||
List<Node> siblings = Arrays.asList(node.getParentNode().getChildren().getNodes());
|
||||
int indexOf = siblings.indexOf(node);
|
||||
//there is no previous for the first node, so instead we select the next one
|
||||
Node sibling = indexOf > 0
|
||||
? siblings.get(indexOf - 1)
|
||||
: siblings.get(indexOf + 1);
|
||||
createPath = NodeOp.createPath(sibling, null);
|
||||
if (siblings.size() > 1) {
|
||||
int indexOf = siblings.indexOf(node);
|
||||
//there is no previous for the first node, so instead we select the next one
|
||||
Node sibling = indexOf > 0
|
||||
? siblings.get(indexOf - 1)
|
||||
: siblings.get(Integer.max(indexOf + 1, siblings.size() - 1));
|
||||
createPath = NodeOp.createPath(sibling, null);
|
||||
} else {
|
||||
/* if there are no other siblings to select,
|
||||
* just return null, but note we need to filter
|
||||
* this out of stream below */
|
||||
return null;
|
||||
}
|
||||
} else {
|
||||
createPath = NodeOp.createPath(node, null);
|
||||
}
|
||||
//for the reselect to work we need to strip off the first part of the path.
|
||||
return Arrays.copyOfRange(createPath, 1, createPath.length);
|
||||
}).collect(Collectors.toList());
|
||||
})
|
||||
.filter(Objects::nonNull)
|
||||
.collect(Collectors.toList());
|
||||
|
||||
//change status of selected artifacts
|
||||
final Collection<? extends BlackboardArtifact> artifacts = Utilities.actionsGlobalContext().lookupAll(BlackboardArtifact.class);
|
||||
@ -1392,7 +1466,7 @@ final public class Accounts implements AutopsyVisitableItem {
|
||||
}
|
||||
}
|
||||
|
||||
class ReviewStatusChangeEvent {
|
||||
private class ReviewStatusChangeEvent {
|
||||
|
||||
Collection<? extends BlackboardArtifact> artifacts;
|
||||
BlackboardArtifact.ReviewStatus newReviewStatus;
|
||||
|
@ -0,0 +1,183 @@
|
||||
package org.sleuthkit.autopsy.datasourceprocessors;
|
||||
|
||||
/*
|
||||
* Autopsy Forensic Browser
|
||||
*
|
||||
* Copyright 2011-2016 Basis Technology Corp.
|
||||
* Contact: carrier <at> sleuthkit <dot> org
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
|
||||
import java.io.File;
|
||||
import java.nio.file.Paths;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import org.sleuthkit.autopsy.casemodule.Case;
|
||||
import org.sleuthkit.autopsy.corecomponentinterfaces.DataSourceProcessorCallback;
|
||||
import org.sleuthkit.autopsy.corecomponentinterfaces.DataSourceProcessorProgressMonitor;
|
||||
import org.sleuthkit.autopsy.coreutils.Logger;
|
||||
import org.sleuthkit.datamodel.Content;
|
||||
import org.sleuthkit.datamodel.Image;
|
||||
import org.sleuthkit.datamodel.SleuthkitCase;
|
||||
import org.sleuthkit.datamodel.TskCoreException;
|
||||
import org.sleuthkit.datamodel.TskFileRange;
|
||||
import org.openide.util.NbBundle.Messages;
|
||||
|
||||
/*
|
||||
* A runnable that adds a raw data source to a case database.
|
||||
*/
|
||||
final class AddRawImageTask implements Runnable {
|
||||
|
||||
private static final Logger logger = Logger.getLogger(AddRawImageTask.class.getName());
|
||||
private final String deviceId;
|
||||
private final String imageFilePath;
|
||||
private final String timeZone;
|
||||
private final long chunkSize;
|
||||
private final DataSourceProcessorProgressMonitor progressMonitor;
|
||||
private final DataSourceProcessorCallback callback;
|
||||
private boolean criticalErrorOccurred;
|
||||
private static final long TWO_GB = 2000000000L;
|
||||
|
||||
/**
|
||||
* Constructs a runnable that adds a raw data source to a case database.
|
||||
*
|
||||
* @param deviceId An ASCII-printable identifier for the
|
||||
* device associated with the data source
|
||||
* that is intended to be unique across
|
||||
* multiple cases (e.g., a UUID).
|
||||
* @param imageFilePath Path to a Raw data source file.
|
||||
* @param timeZone The time zone to use when processing dates
|
||||
* and times for the image, obtained from
|
||||
* java.util.TimeZone.getID.
|
||||
* @param breakupChunks 2GB or not breakup.
|
||||
* @param progressMonitor Progress monitor for reporting
|
||||
* progressMonitor during processing.
|
||||
* @param callback Callback to call when processing is done.
|
||||
*/
|
||||
AddRawImageTask(String deviceId, String imageFilePath, String timeZone, long chunkSize, DataSourceProcessorProgressMonitor progressMonitor, DataSourceProcessorCallback callback) {
|
||||
this.deviceId = deviceId;
|
||||
this.imageFilePath = imageFilePath;
|
||||
this.timeZone = timeZone;
|
||||
this.chunkSize = chunkSize;
|
||||
this.callback = callback;
|
||||
this.progressMonitor = progressMonitor;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a raw data source to a case database.
|
||||
*/
|
||||
@Override
|
||||
public void run() {
|
||||
/*
|
||||
* Process the input image file.
|
||||
*/
|
||||
progressMonitor.setIndeterminate(true);
|
||||
progressMonitor.setProgress(0);
|
||||
List<Content> newDataSources = new ArrayList<>();
|
||||
List<String> errorMessages = new ArrayList<>();
|
||||
addImageToCase(newDataSources, errorMessages);
|
||||
|
||||
progressMonitor.setProgress(100);
|
||||
|
||||
/**
|
||||
* Return the results via the callback passed to the constructor.
|
||||
*/
|
||||
DataSourceProcessorCallback.DataSourceProcessorResult result;
|
||||
if (criticalErrorOccurred) {
|
||||
result = DataSourceProcessorCallback.DataSourceProcessorResult.CRITICAL_ERRORS;
|
||||
} else if (!errorMessages.isEmpty()) {
|
||||
result = DataSourceProcessorCallback.DataSourceProcessorResult.NONCRITICAL_ERRORS;
|
||||
} else {
|
||||
result = DataSourceProcessorCallback.DataSourceProcessorResult.NO_ERRORS;
|
||||
}
|
||||
callback.done(result, errorMessages, newDataSources);
|
||||
criticalErrorOccurred = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Attempts to add the input image to the case.
|
||||
*
|
||||
* @param newDataSources If the image is added, a data source is added to
|
||||
* this list for eventual return to the caller via the
|
||||
* callback.
|
||||
* @param errorMessages If there are any error messages, the error messages
|
||||
* are added to this list for eventual return to the
|
||||
* caller via the callback.
|
||||
*/
|
||||
@Messages({"AddRawImageTask.progress.add.text=Adding raw image: ",
|
||||
"AddRawImageTask.image.critical.error.adding=Critical error adding ",
|
||||
"AddRawImageTask.for.device=for device ",
|
||||
"AddRawImageTask.image.notExisting=is not existing.",
|
||||
"AddRawImageTask.image.noncritical.error.adding=Non-critical error adding "})
|
||||
private void addImageToCase(List<Content> dataSources, List<String> errorMessages) {
|
||||
progressMonitor.setProgressText(Bundle.AddRawImageTask_progress_add_text() + imageFilePath);
|
||||
List<String> imageFilePaths = new ArrayList<>();
|
||||
SleuthkitCase caseDatabase = Case.getCurrentCase().getSleuthkitCase();
|
||||
caseDatabase.acquireExclusiveLock();
|
||||
|
||||
File imageFile = Paths.get(imageFilePath).toFile();
|
||||
if (!imageFile.exists()) {
|
||||
errorMessages.add(Bundle.AddRawImageTask_image_critical_error_adding() + imageFilePath + Bundle.AddRawImageTask_for_device()
|
||||
+ deviceId + Bundle.AddRawImageTask_image_notExisting());
|
||||
criticalErrorOccurred = true;
|
||||
return;
|
||||
}
|
||||
|
||||
imageFilePaths.add(imageFilePath);
|
||||
|
||||
try {
|
||||
/*
|
||||
* Get Image that will be added to case
|
||||
*/
|
||||
Image dataSource = caseDatabase.addImageInfo(0, imageFilePaths, timeZone); //TODO: change hard coded deviceId.
|
||||
dataSources.add(dataSource);
|
||||
List<TskFileRange> fileRanges = new ArrayList<>();
|
||||
|
||||
/*
|
||||
* Verify the size of the new image. Note that it may not be what is
|
||||
* expected, but at least part of it was added to the case.
|
||||
*/
|
||||
String verificationError = dataSource.verifyImageSize();
|
||||
if (!verificationError.isEmpty()) {
|
||||
errorMessages.add(Bundle.AddRawImageTask_image_noncritical_error_adding() + imageFilePaths + Bundle.AddRawImageTask_for_device() + deviceId + ":" + verificationError);
|
||||
}
|
||||
|
||||
long imageSize = dataSource.getSize();
|
||||
int sequence = 0;
|
||||
//start byte and end byte
|
||||
long start = 0;
|
||||
if (chunkSize > 0 && imageSize >= TWO_GB) {
|
||||
for (double size = TWO_GB; size < dataSource.getSize(); size += TWO_GB) {
|
||||
fileRanges.add(new TskFileRange(start, TWO_GB, sequence));
|
||||
start += TWO_GB;
|
||||
sequence++;
|
||||
}
|
||||
|
||||
}
|
||||
double leftoverSize = imageSize - sequence * TWO_GB;
|
||||
fileRanges.add(new TskFileRange(start, (long)leftoverSize, sequence));
|
||||
|
||||
|
||||
caseDatabase.addLayoutFiles(dataSource, fileRanges);
|
||||
|
||||
} catch (TskCoreException ex) {
|
||||
errorMessages.add(Bundle.AddRawImageTask_image_critical_error_adding() + imageFilePaths + Bundle.AddRawImageTask_for_device() + deviceId + ":" + ex.getLocalizedMessage());
|
||||
criticalErrorOccurred = true;
|
||||
} finally {
|
||||
caseDatabase.releaseExclusiveLock();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
12
Core/src/org/sleuthkit/autopsy/datasourceprocessors/Bundle.properties
Executable file
12
Core/src/org/sleuthkit/autopsy/datasourceprocessors/Bundle.properties
Executable file
@ -0,0 +1,12 @@
|
||||
# To change this license header, choose License Headers in Project Properties.
|
||||
# To change this template file, choose Tools | Templates
|
||||
# and open the template in the editor.
|
||||
|
||||
RawDSInputPanel.pathLabel.text=Browse for an unallocated space image file:
|
||||
RawDSInputPanel.errorLabel.text=Error Label
|
||||
RawDSInputPanel.browseButton.text=Browse
|
||||
RawDSInputPanel.pathTextField.text=
|
||||
RawDSInputPanel.jBreakFileUpLabel.text=Break image up into:
|
||||
RawDSInputPanel.jNoBreakupRadioButton.text=Do not break up
|
||||
RawDSInputPanel.j2GBBreakupRadioButton.text=2GB chunks
|
||||
RawDSInputPanel.timeZoneLabel.text=Please select the input timezone:
|
170
Core/src/org/sleuthkit/autopsy/datasourceprocessors/RawDSInputPanel.form
Executable file
170
Core/src/org/sleuthkit/autopsy/datasourceprocessors/RawDSInputPanel.form
Executable file
@ -0,0 +1,170 @@
|
||||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
|
||||
<Form version="1.5" maxVersion="1.8" type="org.netbeans.modules.form.forminfo.JPanelFormInfo">
|
||||
<NonVisualComponents>
|
||||
<Component class="javax.swing.ButtonGroup" name="infileTypeButtonGroup">
|
||||
</Component>
|
||||
</NonVisualComponents>
|
||||
<AuxValues>
|
||||
<AuxValue name="FormSettings_autoResourcing" type="java.lang.Integer" value="1"/>
|
||||
<AuxValue name="FormSettings_autoSetComponentName" type="java.lang.Boolean" value="false"/>
|
||||
<AuxValue name="FormSettings_generateFQN" type="java.lang.Boolean" value="true"/>
|
||||
<AuxValue name="FormSettings_generateMnemonicsCode" type="java.lang.Boolean" value="true"/>
|
||||
<AuxValue name="FormSettings_i18nAutoMode" type="java.lang.Boolean" value="true"/>
|
||||
<AuxValue name="FormSettings_layoutCodeTarget" type="java.lang.Integer" value="1"/>
|
||||
<AuxValue name="FormSettings_listenerGenerationStyle" type="java.lang.Integer" value="0"/>
|
||||
<AuxValue name="FormSettings_variablesLocal" type="java.lang.Boolean" value="false"/>
|
||||
<AuxValue name="FormSettings_variablesModifier" type="java.lang.Integer" value="2"/>
|
||||
</AuxValues>
|
||||
|
||||
<Layout>
|
||||
<DimensionLayout dim="0">
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<Group type="102" alignment="0" attributes="0">
|
||||
<Component id="pathTextField" max="32767" attributes="0"/>
|
||||
<EmptySpace type="unrelated" max="-2" attributes="0"/>
|
||||
<Component id="browseButton" min="-2" pref="77" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
<Group type="102" attributes="0">
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<Component id="pathLabel" min="-2" pref="218" max="-2" attributes="0"/>
|
||||
<Group type="102" attributes="0">
|
||||
<Component id="timeZoneLabel" min="-2" pref="168" max="-2" attributes="0"/>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Component id="timeZoneComboBox" min="-2" pref="199" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
</Group>
|
||||
<EmptySpace min="0" pref="19" max="32767" attributes="0"/>
|
||||
</Group>
|
||||
<Group type="102" attributes="0">
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<Component id="jBreakFileUpLabel" alignment="0" min="-2" max="-2" attributes="0"/>
|
||||
<Component id="errorLabel" alignment="0" min="-2" max="-2" attributes="0"/>
|
||||
<Group type="102" alignment="0" attributes="0">
|
||||
<EmptySpace min="10" pref="10" max="-2" attributes="0"/>
|
||||
<Component id="j2GBBreakupRadioButton" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Component id="jNoBreakupRadioButton" min="-2" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
</Group>
|
||||
<EmptySpace max="32767" attributes="0"/>
|
||||
</Group>
|
||||
</Group>
|
||||
</DimensionLayout>
|
||||
<DimensionLayout dim="1">
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<Group type="102" alignment="0" attributes="0">
|
||||
<Component id="pathLabel" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Group type="103" groupAlignment="3" attributes="0">
|
||||
<Component id="pathTextField" alignment="3" min="-2" max="-2" attributes="0"/>
|
||||
<Component id="browseButton" alignment="3" min="-2" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Group type="103" groupAlignment="3" attributes="0">
|
||||
<Component id="timeZoneLabel" alignment="3" min="-2" max="-2" attributes="0"/>
|
||||
<Component id="timeZoneComboBox" alignment="3" min="-2" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Component id="errorLabel" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace min="-2" pref="5" max="-2" attributes="0"/>
|
||||
<Component id="jBreakFileUpLabel" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace type="unrelated" max="-2" attributes="0"/>
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<Component id="jNoBreakupRadioButton" min="-2" max="-2" attributes="0"/>
|
||||
<Component id="j2GBBreakupRadioButton" alignment="0" min="-2" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
<EmptySpace max="32767" attributes="0"/>
|
||||
</Group>
|
||||
</Group>
|
||||
</DimensionLayout>
|
||||
</Layout>
|
||||
<SubComponents>
|
||||
<Component class="javax.swing.JLabel" name="pathLabel">
|
||||
<Properties>
|
||||
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/datasourceprocessors/Bundle.properties" key="RawDSInputPanel.pathLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
</Component>
|
||||
<Component class="javax.swing.JTextField" name="pathTextField">
|
||||
<Properties>
|
||||
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/datasourceprocessors/Bundle.properties" key="RawDSInputPanel.pathTextField.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
</Component>
|
||||
<Component class="javax.swing.JButton" name="browseButton">
|
||||
<Properties>
|
||||
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/datasourceprocessors/Bundle.properties" key="RawDSInputPanel.browseButton.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
<Events>
|
||||
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="browseButtonActionPerformed"/>
|
||||
</Events>
|
||||
</Component>
|
||||
<Component class="javax.swing.JRadioButton" name="j2GBBreakupRadioButton">
|
||||
<Properties>
|
||||
<Property name="buttonGroup" type="javax.swing.ButtonGroup" editor="org.netbeans.modules.form.RADComponent$ButtonGroupPropertyEditor">
|
||||
<ComponentRef name="infileTypeButtonGroup"/>
|
||||
</Property>
|
||||
<Property name="selected" type="boolean" value="true"/>
|
||||
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/datasourceprocessors/Bundle.properties" key="RawDSInputPanel.j2GBBreakupRadioButton.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
<Events>
|
||||
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="j2GBBreakupRadioButtonActionPerformed"/>
|
||||
</Events>
|
||||
</Component>
|
||||
<Component class="javax.swing.JLabel" name="jBreakFileUpLabel">
|
||||
<Properties>
|
||||
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/datasourceprocessors/Bundle.properties" key="RawDSInputPanel.jBreakFileUpLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
</Component>
|
||||
<Component class="javax.swing.JRadioButton" name="jNoBreakupRadioButton">
|
||||
<Properties>
|
||||
<Property name="buttonGroup" type="javax.swing.ButtonGroup" editor="org.netbeans.modules.form.RADComponent$ButtonGroupPropertyEditor">
|
||||
<ComponentRef name="infileTypeButtonGroup"/>
|
||||
</Property>
|
||||
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/datasourceprocessors/Bundle.properties" key="RawDSInputPanel.jNoBreakupRadioButton.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
<Events>
|
||||
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="jNoBreakupRadioButtonActionPerformed"/>
|
||||
</Events>
|
||||
</Component>
|
||||
<Component class="javax.swing.JLabel" name="errorLabel">
|
||||
<Properties>
|
||||
<Property name="foreground" type="java.awt.Color" editor="org.netbeans.beaninfo.editors.ColorEditor">
|
||||
<Color blue="0" green="0" red="ff" type="rgb"/>
|
||||
</Property>
|
||||
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/datasourceprocessors/Bundle.properties" key="RawDSInputPanel.errorLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
</Component>
|
||||
<Component class="javax.swing.JLabel" name="timeZoneLabel">
|
||||
<Properties>
|
||||
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/datasourceprocessors/Bundle.properties" key="RawDSInputPanel.timeZoneLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
</Component>
|
||||
<Component class="javax.swing.JComboBox" name="timeZoneComboBox">
|
||||
<Properties>
|
||||
<Property name="maximumRowCount" type="int" value="30"/>
|
||||
<Property name="model" type="javax.swing.ComboBoxModel" editor="org.netbeans.modules.form.editors2.ComboBoxModelEditor">
|
||||
<StringArray count="0"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
<AuxValues>
|
||||
<AuxValue name="JavaCodeGenerator_TypeParameters" type="java.lang.String" value="<String>"/>
|
||||
</AuxValues>
|
||||
</Component>
|
||||
</SubComponents>
|
||||
</Form>
|
352
Core/src/org/sleuthkit/autopsy/datasourceprocessors/RawDSInputPanel.java
Executable file
352
Core/src/org/sleuthkit/autopsy/datasourceprocessors/RawDSInputPanel.java
Executable file
@ -0,0 +1,352 @@
|
||||
/*
|
||||
* Autopsy Forensic Browser
|
||||
*
|
||||
* Copyright 2011-2016 Basis Technology Corp.
|
||||
* Contact: carrier <at> sleuthkit <dot> org
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.sleuthkit.autopsy.datasourceprocessors;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.Calendar;
|
||||
import java.util.SimpleTimeZone;
|
||||
import java.util.TimeZone;
|
||||
import javax.swing.JFileChooser;
|
||||
import javax.swing.JPanel;
|
||||
import javax.swing.event.DocumentEvent;
|
||||
import javax.swing.event.DocumentListener;
|
||||
import org.openide.util.NbBundle.Messages;
|
||||
import org.sleuthkit.autopsy.casemodule.Case;
|
||||
import org.sleuthkit.autopsy.corecomponentinterfaces.DataSourceProcessor;
|
||||
import org.sleuthkit.autopsy.coreutils.ModuleSettings;
|
||||
import org.sleuthkit.autopsy.coreutils.PathValidator;
|
||||
|
||||
final class RawDSInputPanel extends JPanel implements DocumentListener {
|
||||
private static final long TWO_GB = 2000000000L;
|
||||
private static final long serialVersionUID = 1L; //default
|
||||
private final String PROP_LASTINPUT_PATH = "LBL_LastInputFile_PATH";
|
||||
private final JFileChooser fc = new JFileChooser();
|
||||
// Externally supplied name is used to store settings
|
||||
private final String contextName;
|
||||
/**
|
||||
* Creates new form RawDSInputPanel
|
||||
*/
|
||||
private RawDSInputPanel(String context) {
|
||||
initComponents();
|
||||
|
||||
errorLabel.setVisible(false);
|
||||
|
||||
fc.setDragEnabled(false);
|
||||
fc.setFileSelectionMode(JFileChooser.FILES_ONLY);
|
||||
fc.setMultiSelectionEnabled(false);
|
||||
|
||||
this.contextName = context;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates and returns an instance of a RawDSInputPanel.
|
||||
*/
|
||||
static synchronized RawDSInputPanel createInstance(String context) {
|
||||
RawDSInputPanel instance = new RawDSInputPanel(context);
|
||||
|
||||
instance.postInit();
|
||||
instance.createTimeZoneList();
|
||||
|
||||
return instance;
|
||||
}
|
||||
|
||||
//post-constructor initialization to properly initialize listener support
|
||||
//without leaking references of uninitialized objects
|
||||
private void postInit() {
|
||||
pathTextField.getDocument().addDocumentListener(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates the drop down list for the time zones and then makes the local
|
||||
* machine time zone to be selected.
|
||||
*/
|
||||
private void createTimeZoneList() {
|
||||
// load and add all timezone
|
||||
String[] ids = SimpleTimeZone.getAvailableIDs();
|
||||
for (String id : ids) {
|
||||
TimeZone zone = TimeZone.getTimeZone(id);
|
||||
int offset = zone.getRawOffset() / 1000;
|
||||
int hour = offset / 3600;
|
||||
int minutes = (offset % 3600) / 60;
|
||||
String item = String.format("(GMT%+d:%02d) %s", hour, minutes, id);
|
||||
|
||||
timeZoneComboBox.addItem(item);
|
||||
}
|
||||
// get the current timezone
|
||||
TimeZone thisTimeZone = Calendar.getInstance().getTimeZone();
|
||||
int thisOffset = thisTimeZone.getRawOffset() / 1000;
|
||||
int thisHour = thisOffset / 3600;
|
||||
int thisMinutes = (thisOffset % 3600) / 60;
|
||||
String formatted = String.format("(GMT%+d:%02d) %s", thisHour, thisMinutes, thisTimeZone.getID());
|
||||
|
||||
// set the selected timezone
|
||||
timeZoneComboBox.setSelectedItem(formatted);
|
||||
}
|
||||
|
||||
/**
|
||||
* 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() {
|
||||
|
||||
infileTypeButtonGroup = new javax.swing.ButtonGroup();
|
||||
pathLabel = new javax.swing.JLabel();
|
||||
pathTextField = new javax.swing.JTextField();
|
||||
browseButton = new javax.swing.JButton();
|
||||
j2GBBreakupRadioButton = new javax.swing.JRadioButton();
|
||||
jBreakFileUpLabel = new javax.swing.JLabel();
|
||||
jNoBreakupRadioButton = new javax.swing.JRadioButton();
|
||||
errorLabel = new javax.swing.JLabel();
|
||||
timeZoneLabel = new javax.swing.JLabel();
|
||||
timeZoneComboBox = new javax.swing.JComboBox<>();
|
||||
|
||||
org.openide.awt.Mnemonics.setLocalizedText(pathLabel, org.openide.util.NbBundle.getMessage(RawDSInputPanel.class, "RawDSInputPanel.pathLabel.text")); // NOI18N
|
||||
|
||||
pathTextField.setText(org.openide.util.NbBundle.getMessage(RawDSInputPanel.class, "RawDSInputPanel.pathTextField.text")); // NOI18N
|
||||
|
||||
org.openide.awt.Mnemonics.setLocalizedText(browseButton, org.openide.util.NbBundle.getMessage(RawDSInputPanel.class, "RawDSInputPanel.browseButton.text")); // NOI18N
|
||||
browseButton.addActionListener(new java.awt.event.ActionListener() {
|
||||
public void actionPerformed(java.awt.event.ActionEvent evt) {
|
||||
browseButtonActionPerformed(evt);
|
||||
}
|
||||
});
|
||||
|
||||
infileTypeButtonGroup.add(j2GBBreakupRadioButton);
|
||||
j2GBBreakupRadioButton.setSelected(true);
|
||||
org.openide.awt.Mnemonics.setLocalizedText(j2GBBreakupRadioButton, org.openide.util.NbBundle.getMessage(RawDSInputPanel.class, "RawDSInputPanel.j2GBBreakupRadioButton.text")); // NOI18N
|
||||
j2GBBreakupRadioButton.addActionListener(new java.awt.event.ActionListener() {
|
||||
public void actionPerformed(java.awt.event.ActionEvent evt) {
|
||||
j2GBBreakupRadioButtonActionPerformed(evt);
|
||||
}
|
||||
});
|
||||
|
||||
org.openide.awt.Mnemonics.setLocalizedText(jBreakFileUpLabel, org.openide.util.NbBundle.getMessage(RawDSInputPanel.class, "RawDSInputPanel.jBreakFileUpLabel.text")); // NOI18N
|
||||
|
||||
infileTypeButtonGroup.add(jNoBreakupRadioButton);
|
||||
org.openide.awt.Mnemonics.setLocalizedText(jNoBreakupRadioButton, org.openide.util.NbBundle.getMessage(RawDSInputPanel.class, "RawDSInputPanel.jNoBreakupRadioButton.text")); // NOI18N
|
||||
jNoBreakupRadioButton.addActionListener(new java.awt.event.ActionListener() {
|
||||
public void actionPerformed(java.awt.event.ActionEvent evt) {
|
||||
jNoBreakupRadioButtonActionPerformed(evt);
|
||||
}
|
||||
});
|
||||
|
||||
errorLabel.setForeground(new java.awt.Color(255, 0, 0));
|
||||
org.openide.awt.Mnemonics.setLocalizedText(errorLabel, org.openide.util.NbBundle.getMessage(RawDSInputPanel.class, "RawDSInputPanel.errorLabel.text")); // NOI18N
|
||||
|
||||
org.openide.awt.Mnemonics.setLocalizedText(timeZoneLabel, org.openide.util.NbBundle.getMessage(RawDSInputPanel.class, "RawDSInputPanel.timeZoneLabel.text")); // NOI18N
|
||||
|
||||
timeZoneComboBox.setMaximumRowCount(30);
|
||||
|
||||
javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
|
||||
this.setLayout(layout);
|
||||
layout.setHorizontalGroup(
|
||||
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
.addGroup(layout.createSequentialGroup()
|
||||
.addComponent(pathTextField)
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
|
||||
.addComponent(browseButton, javax.swing.GroupLayout.PREFERRED_SIZE, 77, javax.swing.GroupLayout.PREFERRED_SIZE))
|
||||
.addGroup(layout.createSequentialGroup()
|
||||
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
.addComponent(pathLabel, javax.swing.GroupLayout.PREFERRED_SIZE, 218, javax.swing.GroupLayout.PREFERRED_SIZE)
|
||||
.addGroup(layout.createSequentialGroup()
|
||||
.addComponent(timeZoneLabel, javax.swing.GroupLayout.PREFERRED_SIZE, 168, javax.swing.GroupLayout.PREFERRED_SIZE)
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||
.addComponent(timeZoneComboBox, javax.swing.GroupLayout.PREFERRED_SIZE, 199, javax.swing.GroupLayout.PREFERRED_SIZE)))
|
||||
.addGap(0, 19, Short.MAX_VALUE))
|
||||
.addGroup(layout.createSequentialGroup()
|
||||
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
.addComponent(jBreakFileUpLabel)
|
||||
.addComponent(errorLabel)
|
||||
.addGroup(layout.createSequentialGroup()
|
||||
.addGap(10, 10, 10)
|
||||
.addComponent(j2GBBreakupRadioButton)
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||
.addComponent(jNoBreakupRadioButton)))
|
||||
.addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
|
||||
);
|
||||
layout.setVerticalGroup(
|
||||
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
.addGroup(layout.createSequentialGroup()
|
||||
.addComponent(pathLabel)
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
|
||||
.addComponent(pathTextField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
|
||||
.addComponent(browseButton))
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
|
||||
.addComponent(timeZoneLabel)
|
||||
.addComponent(timeZoneComboBox, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||
.addComponent(errorLabel)
|
||||
.addGap(5, 5, 5)
|
||||
.addComponent(jBreakFileUpLabel)
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
|
||||
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
.addComponent(jNoBreakupRadioButton)
|
||||
.addComponent(j2GBBreakupRadioButton))
|
||||
.addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
|
||||
);
|
||||
}// </editor-fold>//GEN-END:initComponents
|
||||
@SuppressWarnings("deprecation")
|
||||
private void browseButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_browseButtonActionPerformed
|
||||
String oldText = pathTextField.getText();
|
||||
// set the current directory of the FileChooser if the ImagePath Field is valid
|
||||
File currentDir = new File(oldText);
|
||||
if (currentDir.exists()) {
|
||||
fc.setCurrentDirectory(currentDir);
|
||||
}
|
||||
|
||||
int retval = fc.showOpenDialog(this);
|
||||
if (retval == JFileChooser.APPROVE_OPTION) {
|
||||
String path = fc.getSelectedFile().getPath();
|
||||
pathTextField.setText(path);
|
||||
}
|
||||
}//GEN-LAST:event_browseButtonActionPerformed
|
||||
|
||||
private void j2GBBreakupRadioButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_j2GBBreakupRadioButtonActionPerformed
|
||||
// TODO add your handling code here:
|
||||
}//GEN-LAST:event_j2GBBreakupRadioButtonActionPerformed
|
||||
|
||||
private void jNoBreakupRadioButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jNoBreakupRadioButtonActionPerformed
|
||||
// TODO add your handling code here:
|
||||
}//GEN-LAST:event_jNoBreakupRadioButtonActionPerformed
|
||||
|
||||
// Variables declaration - do not modify//GEN-BEGIN:variables
|
||||
private javax.swing.JButton browseButton;
|
||||
private javax.swing.JLabel errorLabel;
|
||||
private javax.swing.ButtonGroup infileTypeButtonGroup;
|
||||
private javax.swing.JRadioButton j2GBBreakupRadioButton;
|
||||
private javax.swing.JLabel jBreakFileUpLabel;
|
||||
private javax.swing.JRadioButton jNoBreakupRadioButton;
|
||||
private javax.swing.JLabel pathLabel;
|
||||
private javax.swing.JTextField pathTextField;
|
||||
private javax.swing.JComboBox<String> timeZoneComboBox;
|
||||
private javax.swing.JLabel timeZoneLabel;
|
||||
// End of variables declaration//GEN-END:variables
|
||||
/**
|
||||
* Get the path of the user selected image.
|
||||
*
|
||||
* @return the image path
|
||||
*/
|
||||
String getImageFilePath() {
|
||||
return pathTextField.getText();
|
||||
}
|
||||
|
||||
void reset() {
|
||||
//reset the UI elements to default
|
||||
pathTextField.setText(null);
|
||||
j2GBBreakupRadioButton.setSelected(true);
|
||||
}
|
||||
|
||||
long getChunkSize() {
|
||||
if (jNoBreakupRadioButton.isSelected()) {
|
||||
return -1;
|
||||
} else { //if have more choices here, the selection of each radiobutton should be checked
|
||||
return TWO_GB;
|
||||
}
|
||||
}
|
||||
|
||||
String getTimeZone() {
|
||||
String tz = timeZoneComboBox.getSelectedItem().toString();
|
||||
return tz.substring(tz.indexOf(")") + 2).trim();
|
||||
}
|
||||
|
||||
/**
|
||||
* Should we enable the next button of the wizard?
|
||||
*
|
||||
* @return true if a proper image has been selected, false otherwise
|
||||
*/
|
||||
boolean validatePanel() {
|
||||
errorLabel.setVisible(false);
|
||||
String path = getImageFilePath();
|
||||
if (path == null || path.isEmpty()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// display warning if there is one (but don't disable "next" button)
|
||||
warnIfPathIsInvalid(path);
|
||||
|
||||
boolean isExist = new File(path).exists();
|
||||
|
||||
return (isExist);
|
||||
}
|
||||
|
||||
/**
|
||||
* Validates path to selected data source and displays warning if it is
|
||||
* invalid.
|
||||
*
|
||||
* @param path Absolute path to the selected data source
|
||||
*/
|
||||
@Messages({"RawDSInputPanel.error.text=Path to multi-user data source is on \"C:\" drive"})
|
||||
private void warnIfPathIsInvalid(String path) {
|
||||
if (!PathValidator.isValid(path, Case.getCurrentCase().getCaseType())) {
|
||||
errorLabel.setVisible(true);
|
||||
errorLabel.setText(Bundle.RawDSInputPanel_error_text());
|
||||
}
|
||||
}
|
||||
|
||||
void storeSettings() {
|
||||
String inFilePath = getImageFilePath();
|
||||
if (null != inFilePath) {
|
||||
String imagePath = inFilePath.substring(0, inFilePath.lastIndexOf(File.separator) + 1);
|
||||
ModuleSettings.setConfigSetting(contextName, PROP_LASTINPUT_PATH, imagePath);
|
||||
}
|
||||
}
|
||||
|
||||
void readSettings() {
|
||||
String inFilePath = ModuleSettings.getConfigSetting(contextName, PROP_LASTINPUT_PATH);
|
||||
if (null != inFilePath) {
|
||||
if (!inFilePath.isEmpty()) {
|
||||
pathTextField.setText(inFilePath);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Update functions are called by the pathTextField which has this set as
|
||||
* it's DocumentEventListener. Each update function fires a property change
|
||||
* to be caught by the parent panel.
|
||||
*
|
||||
* @param e the event, which is ignored
|
||||
*/
|
||||
@Override
|
||||
public void insertUpdate(DocumentEvent e) {
|
||||
firePropertyChange(DataSourceProcessor.DSP_PANEL_EVENT.UPDATE_UI.toString(), false, true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeUpdate(DocumentEvent e) {
|
||||
firePropertyChange(DataSourceProcessor.DSP_PANEL_EVENT.UPDATE_UI.toString(), false, true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void changedUpdate(DocumentEvent e) {
|
||||
firePropertyChange(DataSourceProcessor.DSP_PANEL_EVENT.UPDATE_UI.toString(), false, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the focus to the pathTextField.
|
||||
*/
|
||||
void select() {
|
||||
pathTextField.requestFocusInWindow();
|
||||
}
|
||||
}
|
@ -0,0 +1,157 @@
|
||||
/*
|
||||
* Autopsy Forensic Browser
|
||||
*
|
||||
* Copyright 2011-2016 Basis Technology Corp.
|
||||
* Contact: carrier <at> sleuthkit <dot> org
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.sleuthkit.autopsy.datasourceprocessors;
|
||||
|
||||
import java.util.UUID;
|
||||
import javax.swing.JPanel;
|
||||
import org.openide.util.NbBundle.Messages;
|
||||
import org.openide.util.lookup.ServiceProvider;
|
||||
import org.sleuthkit.autopsy.corecomponentinterfaces.DataSourceProcessorProgressMonitor;
|
||||
import org.sleuthkit.autopsy.corecomponentinterfaces.DataSourceProcessorCallback;
|
||||
import org.sleuthkit.autopsy.corecomponentinterfaces.DataSourceProcessor;
|
||||
|
||||
/**
|
||||
* A Raw data source processor that implements the DataSourceProcessor service
|
||||
* provider interface to allow integration with the add data source wizard.
|
||||
* It also provides a run method overload to allow it to be used independently
|
||||
* of the wizard.
|
||||
*/
|
||||
@ServiceProvider(service = DataSourceProcessor.class)
|
||||
public class RawDSProcessor implements DataSourceProcessor {
|
||||
private final RawDSInputPanel configPanel;
|
||||
private AddRawImageTask addImageTask;
|
||||
|
||||
/*
|
||||
* Constructs a Raw data source processor that implements the
|
||||
* DataSourceProcessor service provider interface to allow integration
|
||||
* with the add data source wizard. It also provides a run method
|
||||
* overload to allow it to be used independently of the wizard.
|
||||
*/
|
||||
public RawDSProcessor() {
|
||||
configPanel = RawDSInputPanel.createInstance(RawDSProcessor.class.getName());
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a string that describes the type of data sources this processor is
|
||||
* able to add to the case database. The string is suitable for display in a
|
||||
* type selection UI component (e.g., a combo box).
|
||||
*
|
||||
* @return A data source type display string for this data source processor.
|
||||
*/
|
||||
@Messages({"RawDSProcessor.dataSourceType=Unallocated Space Image File"})
|
||||
public static String getType() {
|
||||
return Bundle.RawDSProcessor_dataSourceType();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a string that describes the type of data sources this processor is
|
||||
* able to add to the case database. The string is suitable for display in a
|
||||
* type selection UI component (e.g., a combo box).
|
||||
*
|
||||
* @return A data source type display string for this data source processor.
|
||||
*/
|
||||
@Override
|
||||
public String getDataSourceType() {
|
||||
return Bundle.RawDSProcessor_dataSourceType();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the panel that allows a user to select a data source and do any
|
||||
* configuration required by the data source. The panel is less than 544
|
||||
* pixels wide and less than 173 pixels high.
|
||||
*
|
||||
* @return A selection and configuration panel for this data source
|
||||
* processor.
|
||||
*/
|
||||
@Override
|
||||
public JPanel getPanel() {
|
||||
configPanel.readSettings();
|
||||
configPanel.select();
|
||||
return configPanel;
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicates whether the settings in the selection and configuration panel
|
||||
* are valid and complete.
|
||||
*
|
||||
* @return True if the settings are valid and complete and the processor is
|
||||
* ready to have its run method called, false otherwise.
|
||||
*/
|
||||
@Override
|
||||
public boolean isPanelValid() {
|
||||
return configPanel.validatePanel();
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a data source to the case database using a background task in a
|
||||
* separate thread and the settings provided by the selection and
|
||||
* configuration panel. Returns as soon as the background task is started.
|
||||
* The background task uses a callback object to signal task completion and
|
||||
* return results.
|
||||
*
|
||||
* This method should not be called unless isPanelValid returns true.
|
||||
*
|
||||
* @param progressMonitor Progress monitor that will be used by the
|
||||
* background task to report progress.
|
||||
* @param callback Callback that will be used by the background task
|
||||
* to return results.
|
||||
*/
|
||||
@Override
|
||||
public void run(DataSourceProcessorProgressMonitor progressMonitor, DataSourceProcessorCallback callback) {
|
||||
configPanel.storeSettings();
|
||||
run(UUID.randomUUID().toString(), configPanel.getImageFilePath(), configPanel.getTimeZone(), configPanel.getChunkSize(), progressMonitor, callback);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a data source to the case database using a background task in a
|
||||
* separate thread and the given settings instead of those provided by the
|
||||
* selection and configuration panel. Returns as soon as the background task
|
||||
* is started and uses the callback object to signal task completion and
|
||||
* return results.
|
||||
*
|
||||
* @param deviceId An ASCII-printable identifier for the
|
||||
* device associated with the data source
|
||||
* that is intended to be unique across
|
||||
* multiple cases (e.g., a UUID).
|
||||
* @param rawDSInputFilePath Path to a Raw data source file.
|
||||
* @param isHandsetFile Indicates whether the XML file is for a
|
||||
* handset or a SIM.
|
||||
* @param progressMonitor Progress monitor for reporting progress
|
||||
* during processing.
|
||||
*/
|
||||
private void run(String deviceId, String imageFilePath, String timeZone, long chunkSize, DataSourceProcessorProgressMonitor progressMonitor, DataSourceProcessorCallback callback) {
|
||||
addImageTask = new AddRawImageTask(deviceId, imageFilePath, timeZone, chunkSize, progressMonitor, callback);
|
||||
new Thread(addImageTask).start();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void cancel() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Resets the selection and configuration panel for this data source
|
||||
* processor.
|
||||
*/
|
||||
@Override
|
||||
public void reset() {
|
||||
configPanel.reset();
|
||||
}
|
||||
|
||||
}
|
@ -21,209 +21,244 @@
|
||||
<Layout>
|
||||
<DimensionLayout dim="0">
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<Group type="102" alignment="1" attributes="0">
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Group type="103" groupAlignment="1" attributes="0">
|
||||
<Component id="jSplitPane1" max="32767" attributes="0"/>
|
||||
<Component id="externalViewerTitleLabel" max="32767" attributes="0"/>
|
||||
</Group>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
</Group>
|
||||
<Component id="jPanel1" alignment="1" max="32767" attributes="0"/>
|
||||
</Group>
|
||||
</DimensionLayout>
|
||||
<DimensionLayout dim="1">
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<Group type="102" alignment="0" attributes="0">
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Component id="externalViewerTitleLabel" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Component id="jSplitPane1" pref="458" max="32767" attributes="0"/>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
</Group>
|
||||
<Component id="jPanel1" alignment="1" max="32767" attributes="0"/>
|
||||
</Group>
|
||||
</DimensionLayout>
|
||||
</Layout>
|
||||
<SubComponents>
|
||||
<Component class="javax.swing.JLabel" name="externalViewerTitleLabel">
|
||||
<Properties>
|
||||
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/directorytree/Bundle.properties" key="ExternalViewerGlobalSettingsPanel.externalViewerTitleLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
</Component>
|
||||
<Container class="javax.swing.JSplitPane" name="jSplitPane1">
|
||||
<Properties>
|
||||
<Property name="dividerLocation" type="int" value="350"/>
|
||||
<Property name="dividerSize" type="int" value="1"/>
|
||||
</Properties>
|
||||
<Container class="javax.swing.JPanel" name="jPanel1">
|
||||
|
||||
<Layout class="org.netbeans.modules.form.compat2.layouts.support.JSplitPaneSupportLayout"/>
|
||||
<SubComponents>
|
||||
<Container class="javax.swing.JPanel" name="exePanel">
|
||||
<Constraints>
|
||||
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.support.JSplitPaneSupportLayout" value="org.netbeans.modules.form.compat2.layouts.support.JSplitPaneSupportLayout$JSplitPaneConstraintsDescription">
|
||||
<JSplitPaneConstraints position="right"/>
|
||||
</Constraint>
|
||||
</Constraints>
|
||||
|
||||
<Layout>
|
||||
<DimensionLayout dim="0">
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<Group type="102" attributes="0">
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<Component id="exePathLabel" alignment="0" min="-2" max="-2" attributes="0"/>
|
||||
<Component id="exePathNameLabel" alignment="0" min="-2" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
<EmptySpace pref="114" max="32767" attributes="0"/>
|
||||
</Group>
|
||||
<Layout>
|
||||
<DimensionLayout dim="0">
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<Group type="102" alignment="0" attributes="0">
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Component id="externalViewerTitleLabel" pref="777" max="32767" attributes="0"/>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
</Group>
|
||||
</DimensionLayout>
|
||||
<DimensionLayout dim="1">
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<Group type="103" rootIndex="1" groupAlignment="0" attributes="0">
|
||||
<Group type="102" alignment="0" attributes="0">
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Component id="exePathLabel" min="-2" max="-2" attributes="0"/>
|
||||
<Component id="jScrollPane1" pref="777" max="32767" attributes="0"/>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Component id="exePathNameLabel" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace pref="411" max="32767" attributes="0"/>
|
||||
</Group>
|
||||
</Group>
|
||||
</DimensionLayout>
|
||||
</Layout>
|
||||
<SubComponents>
|
||||
<Component class="javax.swing.JLabel" name="exePathLabel">
|
||||
<Properties>
|
||||
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/directorytree/Bundle.properties" key="ExternalViewerGlobalSettingsPanel.exePathLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
</Component>
|
||||
<Component class="javax.swing.JLabel" name="exePathNameLabel">
|
||||
<Properties>
|
||||
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/directorytree/Bundle.properties" key="ExternalViewerGlobalSettingsPanel.exePathNameLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
</Component>
|
||||
</SubComponents>
|
||||
</Container>
|
||||
<Container class="javax.swing.JPanel" name="rulesPanel">
|
||||
<Constraints>
|
||||
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.support.JSplitPaneSupportLayout" value="org.netbeans.modules.form.compat2.layouts.support.JSplitPaneSupportLayout$JSplitPaneConstraintsDescription">
|
||||
<JSplitPaneConstraints position="left"/>
|
||||
</Constraint>
|
||||
</Constraints>
|
||||
|
||||
<Layout>
|
||||
<DimensionLayout dim="0">
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
</Group>
|
||||
</DimensionLayout>
|
||||
<DimensionLayout dim="1">
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<Group type="102" alignment="0" attributes="0">
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Component id="externalViewerTitleLabel" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace pref="475" max="32767" attributes="0"/>
|
||||
</Group>
|
||||
<Group type="103" rootIndex="1" groupAlignment="0" attributes="0">
|
||||
<Group type="102" attributes="0">
|
||||
<EmptySpace min="-2" pref="32" max="-2" attributes="0"/>
|
||||
<Component id="jScrollPane1" max="32767" attributes="0"/>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
</Group>
|
||||
</Group>
|
||||
</Group>
|
||||
</DimensionLayout>
|
||||
</Layout>
|
||||
<SubComponents>
|
||||
<Component class="javax.swing.JLabel" name="externalViewerTitleLabel">
|
||||
<Properties>
|
||||
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/directorytree/Bundle.properties" key="ExternalViewerGlobalSettingsPanel.externalViewerTitleLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
</Component>
|
||||
<Container class="javax.swing.JScrollPane" name="jScrollPane1">
|
||||
|
||||
<Layout class="org.netbeans.modules.form.compat2.layouts.support.JScrollPaneSupportLayout"/>
|
||||
<SubComponents>
|
||||
<Container class="javax.swing.JSplitPane" name="jSplitPane1">
|
||||
<Properties>
|
||||
<Property name="dividerLocation" type="int" value="350"/>
|
||||
<Property name="dividerSize" type="int" value="1"/>
|
||||
</Properties>
|
||||
|
||||
<Layout class="org.netbeans.modules.form.compat2.layouts.support.JSplitPaneSupportLayout"/>
|
||||
<SubComponents>
|
||||
<Container class="javax.swing.JPanel" name="exePanel">
|
||||
<Constraints>
|
||||
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.support.JSplitPaneSupportLayout" value="org.netbeans.modules.form.compat2.layouts.support.JSplitPaneSupportLayout$JSplitPaneConstraintsDescription">
|
||||
<JSplitPaneConstraints position="right"/>
|
||||
</Constraint>
|
||||
</Constraints>
|
||||
|
||||
<Layout>
|
||||
<DimensionLayout dim="0">
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<Component id="ruleListLabel" alignment="1" max="32767" attributes="0"/>
|
||||
<Group type="102" attributes="0">
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<Component id="rulesScrollPane" alignment="0" min="-2" pref="311" max="-2" attributes="0"/>
|
||||
<Group type="102" alignment="0" attributes="0">
|
||||
<Component id="exePathLabel" alignment="0" min="-2" max="-2" attributes="0"/>
|
||||
<Component id="exePathNameLabel" alignment="0" min="-2" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
<EmptySpace pref="159" max="32767" attributes="0"/>
|
||||
</Group>
|
||||
</Group>
|
||||
</DimensionLayout>
|
||||
<DimensionLayout dim="1">
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<Group type="102" alignment="0" attributes="0">
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Component id="exePathLabel" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Component id="exePathNameLabel" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace pref="408" max="32767" attributes="0"/>
|
||||
</Group>
|
||||
</Group>
|
||||
</DimensionLayout>
|
||||
</Layout>
|
||||
<SubComponents>
|
||||
<Component class="javax.swing.JLabel" name="exePathLabel">
|
||||
<Properties>
|
||||
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/directorytree/Bundle.properties" key="ExternalViewerGlobalSettingsPanel.exePathLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
</Component>
|
||||
<Component class="javax.swing.JLabel" name="exePathNameLabel">
|
||||
<Properties>
|
||||
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/directorytree/Bundle.properties" key="ExternalViewerGlobalSettingsPanel.exePathNameLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
</Component>
|
||||
</SubComponents>
|
||||
</Container>
|
||||
<Container class="javax.swing.JPanel" name="rulesPanel">
|
||||
<Constraints>
|
||||
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.support.JSplitPaneSupportLayout" value="org.netbeans.modules.form.compat2.layouts.support.JSplitPaneSupportLayout$JSplitPaneConstraintsDescription">
|
||||
<JSplitPaneConstraints position="left"/>
|
||||
</Constraint>
|
||||
</Constraints>
|
||||
|
||||
<Layout>
|
||||
<DimensionLayout dim="0">
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<Group type="102" attributes="0">
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<Group type="102" attributes="0">
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<Component id="ruleListLabel" alignment="1" max="32767" attributes="0"/>
|
||||
<Group type="102" attributes="0">
|
||||
<Component id="rulesScrollPane" min="-2" pref="311" max="-2" attributes="0"/>
|
||||
<EmptySpace min="0" pref="0" max="32767" attributes="0"/>
|
||||
</Group>
|
||||
</Group>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
</Group>
|
||||
<Group type="102" attributes="0">
|
||||
<Component id="newRuleButton" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Component id="editRuleButton" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Component id="deleteRuleButton" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace min="0" pref="0" max="32767" attributes="0"/>
|
||||
</Group>
|
||||
</Group>
|
||||
<EmptySpace min="0" pref="18" max="32767" attributes="0"/>
|
||||
</Group>
|
||||
</Group>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
</Group>
|
||||
</Group>
|
||||
</DimensionLayout>
|
||||
<DimensionLayout dim="1">
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<Group type="102" alignment="0" attributes="0">
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Component id="ruleListLabel" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Component id="rulesScrollPane" min="-2" pref="387" max="-2" attributes="0"/>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Group type="103" groupAlignment="3" attributes="0">
|
||||
<Component id="newRuleButton" alignment="3" min="-2" max="-2" attributes="0"/>
|
||||
<Component id="editRuleButton" alignment="3" min="-2" max="-2" attributes="0"/>
|
||||
<Component id="deleteRuleButton" alignment="3" min="-2" max="-2" attributes="0"/>
|
||||
</DimensionLayout>
|
||||
<DimensionLayout dim="1">
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<Group type="102" alignment="0" attributes="0">
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Component id="ruleListLabel" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Component id="rulesScrollPane" pref="380" max="32767" attributes="0"/>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Group type="103" groupAlignment="3" attributes="0">
|
||||
<Component id="newRuleButton" alignment="3" min="-2" max="-2" attributes="0"/>
|
||||
<Component id="editRuleButton" alignment="3" min="-2" max="-2" attributes="0"/>
|
||||
<Component id="deleteRuleButton" alignment="3" min="-2" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
</Group>
|
||||
</Group>
|
||||
<EmptySpace max="32767" attributes="0"/>
|
||||
</Group>
|
||||
</Group>
|
||||
</DimensionLayout>
|
||||
</Layout>
|
||||
<SubComponents>
|
||||
<Component class="javax.swing.JLabel" name="ruleListLabel">
|
||||
<Properties>
|
||||
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/directorytree/Bundle.properties" key="ExternalViewerGlobalSettingsPanel.ruleListLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
</Component>
|
||||
<Container class="javax.swing.JScrollPane" name="rulesScrollPane">
|
||||
<AuxValues>
|
||||
<AuxValue name="autoScrollPane" type="java.lang.Boolean" value="true"/>
|
||||
</AuxValues>
|
||||
</DimensionLayout>
|
||||
</Layout>
|
||||
<SubComponents>
|
||||
<Component class="javax.swing.JLabel" name="ruleListLabel">
|
||||
<Properties>
|
||||
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/directorytree/Bundle.properties" key="ExternalViewerGlobalSettingsPanel.ruleListLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
</Component>
|
||||
<Container class="javax.swing.JScrollPane" name="rulesScrollPane">
|
||||
<AuxValues>
|
||||
<AuxValue name="autoScrollPane" type="java.lang.Boolean" value="true"/>
|
||||
</AuxValues>
|
||||
|
||||
<Layout class="org.netbeans.modules.form.compat2.layouts.support.JScrollPaneSupportLayout"/>
|
||||
<SubComponents>
|
||||
<Component class="javax.swing.JList" name="rulesList">
|
||||
<Properties>
|
||||
<Property name="model" type="javax.swing.ListModel" editor="org.netbeans.modules.form.editors2.ListModelEditor">
|
||||
<StringArray count="0"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
<AuxValues>
|
||||
<AuxValue name="JavaCodeGenerator_TypeParameters" type="java.lang.String" value="<ExternalViewerRule>"/>
|
||||
</AuxValues>
|
||||
</Component>
|
||||
<Layout class="org.netbeans.modules.form.compat2.layouts.support.JScrollPaneSupportLayout"/>
|
||||
<SubComponents>
|
||||
<Component class="javax.swing.JList" name="rulesList">
|
||||
<Properties>
|
||||
<Property name="model" type="javax.swing.ListModel" editor="org.netbeans.modules.form.editors2.ListModelEditor">
|
||||
<StringArray count="0"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
<AuxValues>
|
||||
<AuxValue name="JavaCodeGenerator_TypeParameters" type="java.lang.String" value="<ExternalViewerRule>"/>
|
||||
</AuxValues>
|
||||
</Component>
|
||||
</SubComponents>
|
||||
</Container>
|
||||
<Component class="javax.swing.JButton" name="newRuleButton">
|
||||
<Properties>
|
||||
<Property name="icon" type="javax.swing.Icon" editor="org.netbeans.modules.form.editors2.IconEditor">
|
||||
<Image iconType="3" name="/org/sleuthkit/autopsy/images/add16.png"/>
|
||||
</Property>
|
||||
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/directorytree/Bundle.properties" key="ExternalViewerGlobalSettingsPanel.newRuleButton.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
<Events>
|
||||
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="newRuleButtonActionPerformed"/>
|
||||
</Events>
|
||||
</Component>
|
||||
<Component class="javax.swing.JButton" name="editRuleButton">
|
||||
<Properties>
|
||||
<Property name="icon" type="javax.swing.Icon" editor="org.netbeans.modules.form.editors2.IconEditor">
|
||||
<Image iconType="3" name="/org/sleuthkit/autopsy/images/edit16.png"/>
|
||||
</Property>
|
||||
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/directorytree/Bundle.properties" key="ExternalViewerGlobalSettingsPanel.editRuleButton.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
<Events>
|
||||
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="editRuleButtonActionPerformed"/>
|
||||
</Events>
|
||||
</Component>
|
||||
<Component class="javax.swing.JButton" name="deleteRuleButton">
|
||||
<Properties>
|
||||
<Property name="icon" type="javax.swing.Icon" editor="org.netbeans.modules.form.editors2.IconEditor">
|
||||
<Image iconType="3" name="/org/sleuthkit/autopsy/images/delete16.png"/>
|
||||
</Property>
|
||||
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/directorytree/Bundle.properties" key="ExternalViewerGlobalSettingsPanel.deleteRuleButton.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
<Events>
|
||||
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="deleteRuleButtonActionPerformed"/>
|
||||
</Events>
|
||||
</Component>
|
||||
</SubComponents>
|
||||
</Container>
|
||||
</SubComponents>
|
||||
</Container>
|
||||
<Component class="javax.swing.JButton" name="newRuleButton">
|
||||
<Properties>
|
||||
<Property name="icon" type="javax.swing.Icon" editor="org.netbeans.modules.form.editors2.IconEditor">
|
||||
<Image iconType="3" name="/org/sleuthkit/autopsy/images/add16.png"/>
|
||||
</Property>
|
||||
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/directorytree/Bundle.properties" key="ExternalViewerGlobalSettingsPanel.newRuleButton.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
<Events>
|
||||
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="newRuleButtonActionPerformed"/>
|
||||
</Events>
|
||||
</Component>
|
||||
<Component class="javax.swing.JButton" name="editRuleButton">
|
||||
<Properties>
|
||||
<Property name="icon" type="javax.swing.Icon" editor="org.netbeans.modules.form.editors2.IconEditor">
|
||||
<Image iconType="3" name="/org/sleuthkit/autopsy/images/edit16.png"/>
|
||||
</Property>
|
||||
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/directorytree/Bundle.properties" key="ExternalViewerGlobalSettingsPanel.editRuleButton.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
<Events>
|
||||
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="editRuleButtonActionPerformed"/>
|
||||
</Events>
|
||||
</Component>
|
||||
<Component class="javax.swing.JButton" name="deleteRuleButton">
|
||||
<Properties>
|
||||
<Property name="icon" type="javax.swing.Icon" editor="org.netbeans.modules.form.editors2.IconEditor">
|
||||
<Image iconType="3" name="/org/sleuthkit/autopsy/images/delete16.png"/>
|
||||
</Property>
|
||||
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/directorytree/Bundle.properties" key="ExternalViewerGlobalSettingsPanel.deleteRuleButton.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
<Events>
|
||||
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="deleteRuleButtonActionPerformed"/>
|
||||
</Events>
|
||||
</Component>
|
||||
</SubComponents>
|
||||
</Container>
|
||||
</SubComponents>
|
||||
|
@ -78,7 +78,9 @@ final class ExternalViewerGlobalSettingsPanel extends javax.swing.JPanel impleme
|
||||
// <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
|
||||
private void initComponents() {
|
||||
|
||||
jPanel1 = new javax.swing.JPanel();
|
||||
externalViewerTitleLabel = new javax.swing.JLabel();
|
||||
jScrollPane1 = new javax.swing.JScrollPane();
|
||||
jSplitPane1 = new javax.swing.JSplitPane();
|
||||
exePanel = new javax.swing.JPanel();
|
||||
exePathLabel = new javax.swing.JLabel();
|
||||
@ -111,7 +113,7 @@ final class ExternalViewerGlobalSettingsPanel extends javax.swing.JPanel impleme
|
||||
.addGroup(exePanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
.addComponent(exePathLabel)
|
||||
.addComponent(exePathNameLabel))
|
||||
.addContainerGap(114, Short.MAX_VALUE))
|
||||
.addContainerGap(159, Short.MAX_VALUE))
|
||||
);
|
||||
exePanelLayout.setVerticalGroup(
|
||||
exePanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
@ -120,7 +122,7 @@ final class ExternalViewerGlobalSettingsPanel extends javax.swing.JPanel impleme
|
||||
.addComponent(exePathLabel)
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||
.addComponent(exePathNameLabel)
|
||||
.addContainerGap(411, Short.MAX_VALUE))
|
||||
.addContainerGap(408, Short.MAX_VALUE))
|
||||
);
|
||||
|
||||
jSplitPane1.setRightComponent(exePanel);
|
||||
@ -160,18 +162,20 @@ final class ExternalViewerGlobalSettingsPanel extends javax.swing.JPanel impleme
|
||||
.addGroup(rulesPanelLayout.createSequentialGroup()
|
||||
.addContainerGap()
|
||||
.addGroup(rulesPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
.addComponent(ruleListLabel, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
|
||||
.addGroup(rulesPanelLayout.createSequentialGroup()
|
||||
.addGroup(rulesPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
.addComponent(rulesScrollPane, javax.swing.GroupLayout.PREFERRED_SIZE, 311, javax.swing.GroupLayout.PREFERRED_SIZE)
|
||||
.addComponent(ruleListLabel, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
|
||||
.addGroup(rulesPanelLayout.createSequentialGroup()
|
||||
.addComponent(newRuleButton)
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||
.addComponent(editRuleButton)
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||
.addComponent(deleteRuleButton)))
|
||||
.addGap(0, 18, Short.MAX_VALUE)))
|
||||
.addContainerGap())
|
||||
.addComponent(rulesScrollPane, javax.swing.GroupLayout.PREFERRED_SIZE, 311, javax.swing.GroupLayout.PREFERRED_SIZE)
|
||||
.addGap(0, 0, Short.MAX_VALUE)))
|
||||
.addContainerGap())
|
||||
.addGroup(rulesPanelLayout.createSequentialGroup()
|
||||
.addComponent(newRuleButton)
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||
.addComponent(editRuleButton)
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||
.addComponent(deleteRuleButton)
|
||||
.addGap(0, 0, Short.MAX_VALUE))))
|
||||
);
|
||||
rulesPanelLayout.setVerticalGroup(
|
||||
rulesPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
@ -179,36 +183,55 @@ final class ExternalViewerGlobalSettingsPanel extends javax.swing.JPanel impleme
|
||||
.addContainerGap()
|
||||
.addComponent(ruleListLabel)
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||
.addComponent(rulesScrollPane, javax.swing.GroupLayout.PREFERRED_SIZE, 387, javax.swing.GroupLayout.PREFERRED_SIZE)
|
||||
.addComponent(rulesScrollPane, javax.swing.GroupLayout.DEFAULT_SIZE, 380, Short.MAX_VALUE)
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||
.addGroup(rulesPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
|
||||
.addComponent(newRuleButton)
|
||||
.addComponent(editRuleButton)
|
||||
.addComponent(deleteRuleButton))
|
||||
.addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
|
||||
.addContainerGap())
|
||||
);
|
||||
|
||||
jSplitPane1.setLeftComponent(rulesPanel);
|
||||
|
||||
jScrollPane1.setViewportView(jSplitPane1);
|
||||
|
||||
javax.swing.GroupLayout jPanel1Layout = new javax.swing.GroupLayout(jPanel1);
|
||||
jPanel1.setLayout(jPanel1Layout);
|
||||
jPanel1Layout.setHorizontalGroup(
|
||||
jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
.addGroup(jPanel1Layout.createSequentialGroup()
|
||||
.addContainerGap()
|
||||
.addComponent(externalViewerTitleLabel, javax.swing.GroupLayout.DEFAULT_SIZE, 777, Short.MAX_VALUE)
|
||||
.addContainerGap())
|
||||
.addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
.addGroup(jPanel1Layout.createSequentialGroup()
|
||||
.addContainerGap()
|
||||
.addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 777, Short.MAX_VALUE)
|
||||
.addContainerGap()))
|
||||
);
|
||||
jPanel1Layout.setVerticalGroup(
|
||||
jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
.addGroup(jPanel1Layout.createSequentialGroup()
|
||||
.addContainerGap()
|
||||
.addComponent(externalViewerTitleLabel)
|
||||
.addContainerGap(475, Short.MAX_VALUE))
|
||||
.addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
.addGroup(jPanel1Layout.createSequentialGroup()
|
||||
.addGap(32, 32, 32)
|
||||
.addComponent(jScrollPane1)
|
||||
.addContainerGap()))
|
||||
);
|
||||
|
||||
javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
|
||||
this.setLayout(layout);
|
||||
layout.setHorizontalGroup(
|
||||
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
.addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
|
||||
.addContainerGap()
|
||||
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING)
|
||||
.addComponent(jSplitPane1)
|
||||
.addComponent(externalViewerTitleLabel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
|
||||
.addContainerGap())
|
||||
.addComponent(jPanel1, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
|
||||
);
|
||||
layout.setVerticalGroup(
|
||||
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
.addGroup(layout.createSequentialGroup()
|
||||
.addContainerGap()
|
||||
.addComponent(externalViewerTitleLabel)
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||
.addComponent(jSplitPane1, javax.swing.GroupLayout.PREFERRED_SIZE, 458, Short.MAX_VALUE)
|
||||
.addContainerGap())
|
||||
.addComponent(jPanel1, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
|
||||
);
|
||||
}// </editor-fold>//GEN-END:initComponents
|
||||
|
||||
@ -334,6 +357,8 @@ final class ExternalViewerGlobalSettingsPanel extends javax.swing.JPanel impleme
|
||||
private javax.swing.JLabel exePathLabel;
|
||||
private javax.swing.JLabel exePathNameLabel;
|
||||
private javax.swing.JLabel externalViewerTitleLabel;
|
||||
private javax.swing.JPanel jPanel1;
|
||||
private javax.swing.JScrollPane jScrollPane1;
|
||||
private javax.swing.JSplitPane jSplitPane1;
|
||||
private javax.swing.JButton newRuleButton;
|
||||
private javax.swing.JLabel ruleListLabel;
|
||||
|
@ -165,8 +165,9 @@ class FileSearchPanel extends javax.swing.JPanel {
|
||||
contentList = Collections.<AbstractFile>emptyList();
|
||||
}
|
||||
|
||||
SearchNode sn = new SearchNode(contentList);
|
||||
final TopComponent searchResultWin = DataResultTopComponent.createInstance(title, pathText,
|
||||
new TableFilterNode(new SearchNode(contentList), true), contentList.size());
|
||||
new TableFilterNode(sn, true, sn.getName()), contentList.size());
|
||||
|
||||
searchResultWin.requestActive(); // make it the active top component
|
||||
|
||||
|
@ -16,12 +16,12 @@
|
||||
<Layout>
|
||||
<DimensionLayout dim="0">
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<Component id="jPanel1" alignment="0" pref="838" max="32767" attributes="0"/>
|
||||
<Component id="jPanel1" alignment="0" pref="817" max="32767" attributes="0"/>
|
||||
</Group>
|
||||
</DimensionLayout>
|
||||
<DimensionLayout dim="1">
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<Component id="jPanel1" alignment="0" pref="500" max="32767" attributes="0"/>
|
||||
<Component id="jPanel1" alignment="0" pref="526" max="32767" attributes="0"/>
|
||||
</Group>
|
||||
</DimensionLayout>
|
||||
</Layout>
|
||||
@ -38,7 +38,7 @@
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<Group type="102" attributes="0">
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Component id="jScrollPane1" max="32767" attributes="0"/>
|
||||
<Component id="jScrollPane1" pref="797" max="32767" attributes="0"/>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
</Group>
|
||||
</Group>
|
||||
@ -47,7 +47,7 @@
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<Group type="102" alignment="0" attributes="0">
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Component id="jScrollPane1" max="32767" attributes="0"/>
|
||||
<Component id="jScrollPane1" pref="504" max="32767" attributes="0"/>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
</Group>
|
||||
</Group>
|
||||
@ -79,6 +79,7 @@
|
||||
<Group type="102" attributes="0">
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<Component id="jScrollPane2" alignment="0" pref="0" max="32767" attributes="0"/>
|
||||
<Group type="102" attributes="0">
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<Component id="jLabel1" min="-2" max="-2" attributes="0"/>
|
||||
@ -90,7 +91,6 @@
|
||||
</Group>
|
||||
<EmptySpace min="0" pref="191" max="32767" attributes="0"/>
|
||||
</Group>
|
||||
<Component id="jScrollPane2" alignment="0" pref="409" max="32767" attributes="0"/>
|
||||
</Group>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
</Group>
|
||||
@ -102,7 +102,7 @@
|
||||
<EmptySpace min="-2" max="-2" attributes="0"/>
|
||||
<Component id="jLabel1" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Component id="jScrollPane2" pref="401" max="32767" attributes="0"/>
|
||||
<Component id="jScrollPane2" pref="427" max="32767" attributes="0"/>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Group type="103" groupAlignment="3" attributes="0">
|
||||
<Component id="newTypeButton" alignment="3" min="-2" max="-2" attributes="0"/>
|
||||
@ -175,7 +175,7 @@
|
||||
<Layout>
|
||||
<DimensionLayout dim="0">
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<Group type="102" alignment="0" attributes="0">
|
||||
<Group type="102" attributes="0">
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<Component id="jScrollPane3" pref="0" max="32767" attributes="0"/>
|
||||
@ -188,7 +188,7 @@
|
||||
<Component id="removeExtButton" min="-2" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
</Group>
|
||||
<EmptySpace min="0" pref="40" max="32767" attributes="0"/>
|
||||
<EmptySpace min="0" pref="0" max="32767" attributes="0"/>
|
||||
</Group>
|
||||
</Group>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
@ -201,7 +201,7 @@
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Component id="extHeaderLabel" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Component id="jScrollPane3" pref="401" max="32767" attributes="0"/>
|
||||
<Component id="jScrollPane3" pref="427" max="32767" attributes="0"/>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Group type="103" groupAlignment="3" attributes="0">
|
||||
<Component id="newExtButton" alignment="3" min="-2" max="-2" attributes="0"/>
|
||||
|
@ -188,6 +188,7 @@ final class FileExtMismatchSettingsPanel extends IngestModuleGlobalSettingsPanel
|
||||
.addGroup(mimePanelLayout.createSequentialGroup()
|
||||
.addContainerGap()
|
||||
.addGroup(mimePanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
.addComponent(jScrollPane2, javax.swing.GroupLayout.PREFERRED_SIZE, 0, Short.MAX_VALUE)
|
||||
.addGroup(mimePanelLayout.createSequentialGroup()
|
||||
.addGroup(mimePanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
.addComponent(jLabel1)
|
||||
@ -195,8 +196,7 @@ final class FileExtMismatchSettingsPanel extends IngestModuleGlobalSettingsPanel
|
||||
.addComponent(newTypeButton)
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||
.addComponent(removeTypeButton)))
|
||||
.addGap(0, 191, Short.MAX_VALUE))
|
||||
.addComponent(jScrollPane2, javax.swing.GroupLayout.DEFAULT_SIZE, 409, Short.MAX_VALUE))
|
||||
.addGap(0, 191, Short.MAX_VALUE)))
|
||||
.addContainerGap())
|
||||
);
|
||||
mimePanelLayout.setVerticalGroup(
|
||||
@ -205,7 +205,7 @@ final class FileExtMismatchSettingsPanel extends IngestModuleGlobalSettingsPanel
|
||||
.addContainerGap()
|
||||
.addComponent(jLabel1)
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||
.addComponent(jScrollPane2, javax.swing.GroupLayout.DEFAULT_SIZE, 401, Short.MAX_VALUE)
|
||||
.addComponent(jScrollPane2, javax.swing.GroupLayout.DEFAULT_SIZE, 427, Short.MAX_VALUE)
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||
.addGroup(mimePanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
|
||||
.addComponent(newTypeButton)
|
||||
@ -251,7 +251,7 @@ final class FileExtMismatchSettingsPanel extends IngestModuleGlobalSettingsPanel
|
||||
.addComponent(newExtButton)
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||
.addComponent(removeExtButton)))
|
||||
.addGap(0, 40, Short.MAX_VALUE)))
|
||||
.addGap(0, 0, Short.MAX_VALUE)))
|
||||
.addContainerGap())
|
||||
);
|
||||
extensionPanelLayout.setVerticalGroup(
|
||||
@ -260,7 +260,7 @@ final class FileExtMismatchSettingsPanel extends IngestModuleGlobalSettingsPanel
|
||||
.addContainerGap()
|
||||
.addComponent(extHeaderLabel)
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||
.addComponent(jScrollPane3, javax.swing.GroupLayout.DEFAULT_SIZE, 401, Short.MAX_VALUE)
|
||||
.addComponent(jScrollPane3, javax.swing.GroupLayout.DEFAULT_SIZE, 427, Short.MAX_VALUE)
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||
.addGroup(extensionPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
|
||||
.addComponent(newExtButton)
|
||||
@ -278,14 +278,14 @@ final class FileExtMismatchSettingsPanel extends IngestModuleGlobalSettingsPanel
|
||||
jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
.addGroup(jPanel1Layout.createSequentialGroup()
|
||||
.addContainerGap()
|
||||
.addComponent(jScrollPane1)
|
||||
.addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 797, Short.MAX_VALUE)
|
||||
.addContainerGap())
|
||||
);
|
||||
jPanel1Layout.setVerticalGroup(
|
||||
jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
.addGroup(jPanel1Layout.createSequentialGroup()
|
||||
.addContainerGap()
|
||||
.addComponent(jScrollPane1)
|
||||
.addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 504, Short.MAX_VALUE)
|
||||
.addContainerGap())
|
||||
);
|
||||
|
||||
@ -293,11 +293,11 @@ final class FileExtMismatchSettingsPanel extends IngestModuleGlobalSettingsPanel
|
||||
this.setLayout(layout);
|
||||
layout.setHorizontalGroup(
|
||||
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
.addComponent(jPanel1, javax.swing.GroupLayout.DEFAULT_SIZE, 838, Short.MAX_VALUE)
|
||||
.addComponent(jPanel1, javax.swing.GroupLayout.DEFAULT_SIZE, 817, Short.MAX_VALUE)
|
||||
);
|
||||
layout.setVerticalGroup(
|
||||
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
.addComponent(jPanel1, javax.swing.GroupLayout.DEFAULT_SIZE, 500, Short.MAX_VALUE)
|
||||
.addComponent(jPanel1, javax.swing.GroupLayout.DEFAULT_SIZE, 526, Short.MAX_VALUE)
|
||||
);
|
||||
}// </editor-fold>//GEN-END:initComponents
|
||||
|
||||
|
@ -28,12 +28,10 @@ FileTypeIdGlobalSettingsPanel.JOptionPane.invalidInterestingFilesSetName.message
|
||||
FileTypeIdGlobalSettingsPanel.JOptionPane.invalidInterestingFilesSetName.title=Missing Interesting Files Set Name
|
||||
FileTypeIdGlobalSettingsPanel.JOptionPane.storeFailed.title=Save Failed
|
||||
FileTypeIdGlobalSettingsPanel.JOptionPane.loadFailed.title=Load Failed
|
||||
FileTypeIdGlobalSettingsPanel.ingestRunningWarningLabel.text=Cannot make changes to file type definitions when ingest is running!
|
||||
FileTypeIdGlobalSettingsPanel.loadFileTypes.errorMessage=Failed to load existing file type definitions.
|
||||
FileTypeIdGlobalSettingsPanel.saveFileTypes.errorMessage=Failed to save file type definitions.
|
||||
FileTypeIdGlobalSettingsPanel.newTypeButton.text=New Type
|
||||
FileTypeIdGlobalSettingsPanel.jLabel2.text=Custom MIME Types:
|
||||
FileTypeIdGlobalSettingsPanel.jLabel3.text=Autopsy can automatically detect many file types. Add your custom file types here.
|
||||
FileTypeIdGlobalSettingsPanel.startUp.fileTypeDetectorInitializationException.msg=Error initializing the file type detector.
|
||||
AddFileTypeSignaturePanel.offsetLabel.text=Byte Offset
|
||||
AddFileTypeSignaturePanel.signatureTextField.text=
|
||||
@ -53,3 +51,5 @@ AddFileTypePanel.addSigButton.text=Add Signature
|
||||
AddFileTypePanel.postHitCheckBox.text=Alert as an "Interesting File" when found
|
||||
AddFileTypePanel.setNameLabel.text=Set Name
|
||||
AddFileTypePanel.setNameTextField.text=
|
||||
FileTypeIdGlobalSettingsPanel.ingestRunningWarningLabel.text=Cannot make changes to file type definitions when ingest is running!
|
||||
FileTypeIdGlobalSettingsPanel.jLabel3.text=Autopsy can automatically detect many file types. Add your custom file types here.
|
||||
|
@ -9,7 +9,6 @@ FileTypeIdModuleFactory.createFileIngestModule.exception.msg=\u8a2d\u5b9a\u3092\
|
||||
FileTypeIdIngestJobSettingsPanel.skipKnownCheckBox.toolTipText=\u65e2\u77e5\u306e\u30cf\u30c3\u30b7\u30e5\u5024\u3092\u6301\u3064\u30d5\u30a1\u30a4\u30eb\u6570\u306b\u3088\u3063\u3066\u306f\u3001\u3053\u306e\u30dc\u30c3\u30af\u30b9\u3092\u9078\u629e\u3059\u308b\u3053\u3068\u306b\u3088\u308a\u3001\u30d5\u30a1\u30a4\u30eb\u30bf\u30a4\u30d7\u306e\u7279\u5b9a\u3092\u52a0\u901f\u3057\u307e\u3059\u3002
|
||||
FileTypeIdIngestJobSettingsPanel.skipKnownCheckBox.text=\u65e2\u77e5\u30d5\u30a1\u30a4\u30eb\uff08NSRL\uff09\u3092\u30b9\u30ad\u30c3\u30d7
|
||||
FileTypeIdGlobalSettingsPanel.deleteTypeButton.text=\u524a\u9664
|
||||
FileTypeIdGlobalSettingsPanel.ingestRunningWarningLabel.text=\u30a4\u30f3\u30b8\u30a7\u30b9\u30c8\u3092\u5b9f\u884c\u4e2d\u306b\u30d5\u30a1\u30a4\u30eb\u30bf\u30a4\u30d7\u5b9a\u7fa9\u3092\u5909\u66f4\u3067\u304d\u307e\u305b\u3093\uff01
|
||||
FileTypeIdGlobalSettingsPanel.JOptionPane.invalidInterestingFilesSetName.title=\u7591\u308f\u3057\u3044\u30d5\u30a1\u30a4\u30eb\u30bb\u30c3\u30c8\u540d\u304c\u6b20\u3051\u3066\u3044\u307e\u3059
|
||||
FileTypeIdGlobalSettingsPanel.JOptionPane.invalidMIMEType.message=MIME\u30bf\u30a4\u30d7\u304c\u5fc5\u8981\u3067\u3059\u3002
|
||||
FileTypeIdGlobalSettingsPanel.JOptionPane.invalidMIMEType.title=MIME\u30bf\u30a4\u30d7\u304c\u6b20\u3051\u3066\u3044\u307e\u3059
|
||||
@ -33,10 +32,11 @@ FileTypeIdGlobalSettingsPanel.offsetComboBox.startItem=\u958b\u59cb
|
||||
FileTypeIdGlobalSettingsPanel.offsetComboBox.endItem=\u505c\u6b62
|
||||
FileTypeIdGlobalSettingsPanel.JOptionPane.invalidOffset.length=\u30aa\u30d5\u30bb\u30c3\u30c8\u306f\u30b7\u30b0\u30cd\u30c1\u30e3\u30b5\u30a4\u30ba\u3088\u308a\u5c0f\u3055\u304f\u3066\u306f\u3044\u3051\u307e\u305b\u3093\u3002
|
||||
FileTypeIdGlobalSettingsPanel.jLabel2.text=MIME\u30bf\u30a4\u30d7\uff1a
|
||||
FileTypeIdGlobalSettingsPanel.jLabel3.text=Autopsy\u306f\u81ea\u52d5\u7684\u306b\u591a\u304f\u306e\u30d5\u30a1\u30a4\u30eb\u30bf\u30a4\u30d7\u3092\u691c\u77e5\u3067\u304d\u307e\u3059\u3002\u3053\u3053\u306b\u306f\u3042\u306a\u305f\u306e\u30ab\u30b9\u30bf\u30e0\u306e\u30d5\u30a1\u30a4\u30eb\u30bf\u30a4\u30d7\u3092\u5165\u529b\u3057\u3066\u304f\u3060\u3055\u3044\u3002
|
||||
FileTypeIdGlobalSettingsPanel.startUp.fileTypeDetectorInitializationException.msg=\u30d5\u30a1\u30a4\u30eb\u30bf\u30a4\u30d7\u30c7\u30a3\u30c6\u30af\u30bf\u3092\u8d77\u52d5\u4e2d\u306b\u30a8\u30e9\u30fc\u304c\u767a\u751f\u3057\u307e\u3057\u305f\u3002
|
||||
AddFileTypeSignaturePanel.signatureTypeLabel.text=\u30b7\u30b0\u30cd\u30c1\u30e3\u30bf\u30a4\u30d7
|
||||
AddFileTypeSignaturePanel.signatureLabel.text=\u30b7\u30b0\u30cd\u30c1\u30e3
|
||||
AddFileTypeSignaturePanel.offsetRelativeToLabel.text=\u30aa\u30d5\u30bb\u30c3\u30c8\u306f\u6b21\u3068\u76f8\u5bfe\u7684
|
||||
AddFileTypeSignaturePanel.offsetLabel.text=\u30d0\u30a4\u30c8\u30aa\u30d5\u30bb\u30c3\u30c8
|
||||
AddFileTypePanel.mimeTypeLabel.text=MIME\u30bf\u30a4\u30d7
|
||||
FileTypeIdGlobalSettingsPanel.ingestRunningWarningLabel.text=\u30a4\u30f3\u30b8\u30a7\u30b9\u30c8\u3092\u5b9f\u884c\u4e2d\u306b\u30d5\u30a1\u30a4\u30eb\u30bf\u30a4\u30d7\u5b9a\u7fa9\u3092\u5909\u66f4\u3067\u304d\u307e\u305b\u3093\uff01
|
||||
FileTypeIdGlobalSettingsPanel.jLabel3.text=Autopsy\u306f\u81ea\u52d5\u7684\u306b\u591a\u304f\u306e\u30d5\u30a1\u30a4\u30eb\u30bf\u30a4\u30d7\u3092\u691c\u77e5\u3067\u304d\u307e\u3059\u3002\u3053\u3053\u306b\u306f\u3042\u306a\u305f\u306e\u30ab\u30b9\u30bf\u30e0\u306e\u30d5\u30a1\u30a4\u30eb\u30bf\u30a4\u30d7\u3092\u5165\u529b\u3057\u3066\u304f\u3060\u3055\u3044\u3002
|
||||
|
@ -51,14 +51,6 @@
|
||||
</Properties>
|
||||
</Component>
|
||||
</NonVisualComponents>
|
||||
<Properties>
|
||||
<Property name="minimumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
|
||||
<Dimension value="[700, 500]"/>
|
||||
</Property>
|
||||
<Property name="preferredSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
|
||||
<Dimension value="[750, 500]"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
<AuxValues>
|
||||
<AuxValue name="FormSettings_autoResourcing" type="java.lang.Integer" value="1"/>
|
||||
<AuxValue name="FormSettings_autoSetComponentName" type="java.lang.Boolean" value="false"/>
|
||||
@ -74,15 +66,12 @@
|
||||
<Layout>
|
||||
<DimensionLayout dim="0">
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<Component id="jScrollPane2" alignment="0" max="32767" attributes="0"/>
|
||||
<Component id="jScrollPane2" alignment="0" pref="789" max="32767" attributes="0"/>
|
||||
</Group>
|
||||
</DimensionLayout>
|
||||
<DimensionLayout dim="1">
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<Group type="102" alignment="0" attributes="0">
|
||||
<Component id="jScrollPane2" max="32767" attributes="0"/>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
</Group>
|
||||
<Component id="jScrollPane2" alignment="0" max="32767" attributes="0"/>
|
||||
</Group>
|
||||
</DimensionLayout>
|
||||
</Layout>
|
||||
@ -156,7 +145,7 @@
|
||||
<Group type="102" attributes="0">
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<Component id="hashDatabasesLabel" min="-2" max="-2" attributes="0"/>
|
||||
<Group type="102" alignment="0" attributes="0">
|
||||
<Group type="102" attributes="0">
|
||||
<Component id="createDatabaseButton" min="-2" pref="121" max="-2" attributes="0"/>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Component id="importDatabaseButton" min="-2" pref="132" max="-2" attributes="0"/>
|
||||
@ -167,7 +156,6 @@
|
||||
<EmptySpace min="0" pref="0" max="32767" attributes="0"/>
|
||||
</Group>
|
||||
</Group>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
</Group>
|
||||
</Group>
|
||||
</DimensionLayout>
|
||||
@ -225,8 +213,9 @@
|
||||
<Component id="sendIngestMessagesCheckBox" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace type="separate" max="-2" attributes="0"/>
|
||||
<Component id="ingestWarningLabel" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace min="0" pref="0" max="32767" attributes="0"/>
|
||||
</Group>
|
||||
<Component id="jScrollPane1" min="-2" pref="423" max="-2" attributes="0"/>
|
||||
<Component id="jScrollPane1" max="32767" attributes="0"/>
|
||||
</Group>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Group type="103" groupAlignment="3" attributes="0">
|
||||
@ -234,7 +223,7 @@
|
||||
<Component id="importDatabaseButton" alignment="3" min="-2" max="-2" attributes="0"/>
|
||||
<Component id="deleteDatabaseButton" alignment="3" min="-2" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
<EmptySpace pref="29" max="32767" attributes="0"/>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
</Group>
|
||||
</Group>
|
||||
</DimensionLayout>
|
||||
|
@ -527,9 +527,6 @@ public final class HashLookupSettingsPanel extends IngestModuleGlobalSettingsPan
|
||||
jButton3.setFont(jButton3.getFont().deriveFont(jButton3.getFont().getStyle() & ~java.awt.Font.BOLD, 14));
|
||||
org.openide.awt.Mnemonics.setLocalizedText(jButton3, org.openide.util.NbBundle.getMessage(HashLookupSettingsPanel.class, "HashLookupSettingsPanel.jButton3.text")); // NOI18N
|
||||
|
||||
setMinimumSize(new java.awt.Dimension(700, 500));
|
||||
setPreferredSize(new java.awt.Dimension(750, 500));
|
||||
|
||||
ingestWarningLabel.setFont(ingestWarningLabel.getFont().deriveFont(ingestWarningLabel.getFont().getStyle() & ~java.awt.Font.BOLD, 11));
|
||||
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(HashLookupSettingsPanel.class, "HashLookupSettingsPanel.ingestWarningLabel.text")); // NOI18N
|
||||
@ -712,8 +709,7 @@ public final class HashLookupSettingsPanel extends IngestModuleGlobalSettingsPan
|
||||
.addComponent(importDatabaseButton, javax.swing.GroupLayout.PREFERRED_SIZE, 132, javax.swing.GroupLayout.PREFERRED_SIZE)
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||
.addComponent(deleteDatabaseButton, javax.swing.GroupLayout.PREFERRED_SIZE, 131, javax.swing.GroupLayout.PREFERRED_SIZE)))
|
||||
.addGap(0, 0, Short.MAX_VALUE)))
|
||||
.addContainerGap())
|
||||
.addGap(0, 0, Short.MAX_VALUE))))
|
||||
);
|
||||
jPanel1Layout.setVerticalGroup(
|
||||
jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
@ -759,14 +755,15 @@ public final class HashLookupSettingsPanel extends IngestModuleGlobalSettingsPan
|
||||
.addGap(18, 18, 18)
|
||||
.addComponent(sendIngestMessagesCheckBox)
|
||||
.addGap(18, 18, 18)
|
||||
.addComponent(ingestWarningLabel))
|
||||
.addComponent(jScrollPane1, javax.swing.GroupLayout.PREFERRED_SIZE, 423, javax.swing.GroupLayout.PREFERRED_SIZE))
|
||||
.addComponent(ingestWarningLabel)
|
||||
.addGap(0, 0, Short.MAX_VALUE))
|
||||
.addComponent(jScrollPane1))
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||
.addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
|
||||
.addComponent(createDatabaseButton, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
|
||||
.addComponent(importDatabaseButton, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
|
||||
.addComponent(deleteDatabaseButton, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
|
||||
.addContainerGap(29, Short.MAX_VALUE))
|
||||
.addContainerGap())
|
||||
);
|
||||
|
||||
jScrollPane2.setViewportView(jPanel1);
|
||||
@ -775,13 +772,11 @@ public final class HashLookupSettingsPanel extends IngestModuleGlobalSettingsPan
|
||||
this.setLayout(layout);
|
||||
layout.setHorizontalGroup(
|
||||
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
.addComponent(jScrollPane2)
|
||||
.addComponent(jScrollPane2, javax.swing.GroupLayout.DEFAULT_SIZE, 789, Short.MAX_VALUE)
|
||||
);
|
||||
layout.setVerticalGroup(
|
||||
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
.addGroup(layout.createSequentialGroup()
|
||||
.addComponent(jScrollPane2)
|
||||
.addContainerGap())
|
||||
.addComponent(jScrollPane2)
|
||||
);
|
||||
}// </editor-fold>//GEN-END:initComponents
|
||||
|
||||
|
@ -29,7 +29,7 @@
|
||||
<Layout>
|
||||
<DimensionLayout dim="0">
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<Component id="jScrollPane1" alignment="0" pref="762" max="32767" attributes="0"/>
|
||||
<Component id="jScrollPane1" alignment="0" max="32767" attributes="0"/>
|
||||
</Group>
|
||||
</DimensionLayout>
|
||||
<DimensionLayout dim="1">
|
||||
|
@ -901,7 +901,7 @@ final class InterestingItemDefsPanel extends IngestModuleGlobalSettingsPanel imp
|
||||
this.setLayout(layout);
|
||||
layout.setHorizontalGroup(
|
||||
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
.addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 762, Short.MAX_VALUE)
|
||||
.addComponent(jScrollPane1)
|
||||
);
|
||||
layout.setVerticalGroup(
|
||||
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
|
@ -1,6 +1,5 @@
|
||||
VMExtractorIngestModuleFactory.moduleDisplayName=Virtual Machine Extractor
|
||||
VMExtractorIngestModuleFactory.moduleDescription=Extracts virtual machine files and adds them to a case as data sources.
|
||||
VMExtractorIngestModuleFactory.version=1.0
|
||||
VMExtractorIngestModule.addedVirtualMachineImage.message=Added virtual machine image {0}
|
||||
VMExtractorIngestModule.searchingImage.message=Searching image for virtual machine files
|
||||
VMExtractorIngestModule.exportingToDisk.message=Exporting virtual machine files to disk
|
||||
|
@ -20,6 +20,7 @@ package org.sleuthkit.autopsy.modules.vmextractor;
|
||||
|
||||
import org.openide.util.NbBundle;
|
||||
import org.openide.util.lookup.ServiceProvider;
|
||||
import org.sleuthkit.autopsy.coreutils.Version;
|
||||
import org.sleuthkit.autopsy.ingest.DataSourceIngestModule;
|
||||
import org.sleuthkit.autopsy.ingest.IngestModuleFactory;
|
||||
import org.sleuthkit.autopsy.ingest.IngestModuleFactoryAdapter;
|
||||
@ -53,7 +54,7 @@ public final class VMExtractorIngestModuleFactory extends IngestModuleFactoryAda
|
||||
|
||||
@Override
|
||||
public String getModuleVersionNumber() {
|
||||
return NbBundle.getMessage(this.getClass(), "VMExtractorIngestModuleFactory.version");
|
||||
return Version.getVersion();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -170,6 +170,8 @@ class ReportGenerator {
|
||||
TableReportGenerator generator = new TableReportGenerator(artifactTypeSelections, tagNameSelections, progressPanel, tableReport);
|
||||
generator.execute();
|
||||
tableReport.endReport();
|
||||
// finish progress, wrap up
|
||||
progressPanel.complete(ReportProgressPanel.ReportStatus.COMPLETE);
|
||||
errorList = generator.getErrorList();
|
||||
});
|
||||
worker.execute();
|
||||
|
@ -114,9 +114,6 @@ class TableReportGenerator {
|
||||
// report on the tagged images
|
||||
makeThumbnailTable();
|
||||
}
|
||||
|
||||
// finish progress, wrap up
|
||||
progressPanel.complete(ReportProgressPanel.ReportStatus.COMPLETE);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -1495,6 +1492,9 @@ class TableReportGenerator {
|
||||
} else if (artifactTypeId == BlackboardArtifact.ARTIFACT_TYPE.TSK_ACCOUNT.getTypeID()) {
|
||||
columns.add(new StatusColumn());
|
||||
attributeTypeSet.remove(new Type(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_ACCOUNT_TYPE));
|
||||
attributeTypeSet.remove(new Type(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_ASSOCIATED_ARTIFACT));
|
||||
attributeTypeSet.remove(new Type(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_SET_NAME));
|
||||
attributeTypeSet.remove(new Type(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_KEYWORD_SEARCH_DOCUMENT_ID));
|
||||
} else {
|
||||
// This is the case that it is a custom type. The reason an else is
|
||||
// necessary is to make sure that the source file column is added
|
||||
|
@ -16,7 +16,7 @@
|
||||
<dependency conf="autopsy_core->*" org="org.jbundle.thin.base.screen" name="jcalendarbutton" rev="1.4.6"/>
|
||||
|
||||
<!-- commmon -->
|
||||
<dependency org="com.google.guava" name="guava" rev="18.0"/>
|
||||
<dependency org="com.google.guava" name="guava" rev="19.0"/>
|
||||
<dependency conf="autopsy_core->*" org="org.apache.commons" name="commons-lang3" rev="3.0"/>
|
||||
<dependency conf="autopsy_core->*" org="org.apache.commons" name="commons-csv" rev="1.4"/>
|
||||
|
||||
|
@ -22,7 +22,7 @@ file.reference.dom4j-1.6.1.jar=release/modules/ext/dom4j-1.6.1.jar
|
||||
file.reference.geronimo-jms_1.1_spec-1.0.jar=release/modules/ext/geronimo-jms_1.1_spec-1.0.jar
|
||||
file.reference.gson-1.4.jar=release/modules/ext/gson-1.4.jar
|
||||
file.reference.gstreamer-java-1.5.jar=release/modules/ext/gstreamer-java-1.5.jar
|
||||
file.reference.guava-18.0.jar=release/modules/ext/guava-18.0.jar
|
||||
file.reference.guava-19.0.jar=release/modules/ext/guava-19.0.jar
|
||||
file.reference.imageio-bmp-3.2.jar=release/modules/ext/imageio-bmp-3.2.jar
|
||||
file.reference.imageio-core-3.2.jar=release/modules/ext/imageio-core-3.2.jar
|
||||
file.reference.imageio-icns-3.2.jar=release/modules/ext/imageio-icns-3.2.jar
|
||||
@ -75,7 +75,7 @@ javac.compilerargs=-Xlint -Xlint:-serial
|
||||
javadoc.reference.commons-csv-1.4.jar=release/modules/ext/commons-csv-1.4-javadoc.jar
|
||||
javadoc.reference.compiler-0.9.1.jar=release/modules/ext/compiler-0.9.1-javadoc.jar
|
||||
javadoc.reference.controlsfx-8.40.11.jar=release/modules/ext/controlsfx-8.40.11-javadoc.jar
|
||||
javadoc.reference.guava-18.0.jar=release/modules/ext/guava-18.0-javadoc.jar
|
||||
javadoc.reference.guava-19.0.jar=release/modules/ext/guava-19.0-javadoc.jar
|
||||
javadoc.reference.jfxtras-common-8.0-r4.jar=release/modules/ext/jfxtras-common-8.0-r4-javadoc.jar
|
||||
javadoc.reference.jfxtras-controls-8.0-r4.jar=release/modules/ext/jfxtras-controls-8.0-r4-javadoc.jar
|
||||
javadoc.reference.jfxtras-fxml-8.0-r4.jar=release/modules/ext/jfxtras-fxml-8.0-r4-javadoc.jar
|
||||
@ -83,7 +83,7 @@ nbm.needs.restart=true
|
||||
source.reference.commons-csv-1.4.jar=release/modules/ext/commons-csv-1.4-sources.jar
|
||||
source.reference.compiler-0.9.1.jar=release/modules/ext/compiler-0.9.1-sources.jar
|
||||
source.reference.controlsfx-8.40.11.jar=release/modules/ext/controlsfx-8.40.11-sources.jar
|
||||
source.reference.guava-18.0.jar=release/modules/ext/guava-18.0-sources.jar
|
||||
source.reference.guava-19.0.jar=release/modules/ext/guava-19.0-sources.jar
|
||||
source.reference.jfxtras-common-8.0-r4.jar=release/modules/ext/jfxtras-common-8.0-r4-sources.jar
|
||||
source.reference.jfxtras-controls-8.0-r4.jar=release/modules/ext/jfxtras-controls-8.0-r4-sources.jar
|
||||
source.reference.jfxtras-fxml-8.0-r4.jar=release/modules/ext/jfxtras-fxml-8.0-r4-sources.jar
|
||||
|
@ -743,10 +743,6 @@
|
||||
<runtime-relative-path>ext/mail-1.4.3.jar</runtime-relative-path>
|
||||
<binary-origin>release/modules/ext/mail-1.4.3.jar</binary-origin>
|
||||
</class-path-extension>
|
||||
<class-path-extension>
|
||||
<runtime-relative-path>ext/guava-18.0.jar</runtime-relative-path>
|
||||
<binary-origin>release/modules/ext/guava-18.0.jar</binary-origin>
|
||||
</class-path-extension>
|
||||
<class-path-extension>
|
||||
<runtime-relative-path>ext/imageio-tga-3.2.jar</runtime-relative-path>
|
||||
<binary-origin>release/modules/ext/imageio-tga-3.2.jar</binary-origin>
|
||||
@ -851,6 +847,10 @@
|
||||
<runtime-relative-path>ext/slf4j-simple-1.6.1.jar</runtime-relative-path>
|
||||
<binary-origin>release/modules/ext/slf4j-simple-1.6.1.jar</binary-origin>
|
||||
</class-path-extension>
|
||||
<class-path-extension>
|
||||
<runtime-relative-path>ext/guava-19.0.jar</runtime-relative-path>
|
||||
<binary-origin>release/modules/ext/guava-19.0.jar</binary-origin>
|
||||
</class-path-extension>
|
||||
<class-path-extension>
|
||||
<runtime-relative-path>ext/imageio-bmp-3.2.jar</runtime-relative-path>
|
||||
<binary-origin>release/modules/ext/imageio-bmp-3.2.jar</binary-origin>
|
||||
|
@ -1,7 +1,7 @@
|
||||
/*
|
||||
* Autopsy Forensic Browser
|
||||
*
|
||||
* Copyright 2012 Basis Technology Corp.
|
||||
* Copyright 2011-2016 Basis Technology Corp.
|
||||
* Contact: carrier <at> sleuthkit <dot> org
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
@ -19,47 +19,73 @@
|
||||
package org.sleuthkit.autopsy.keywordsearch;
|
||||
|
||||
import java.nio.charset.Charset;
|
||||
import org.openide.util.NbBundle;
|
||||
import org.sleuthkit.autopsy.keywordsearch.Ingester.IngesterException;
|
||||
|
||||
/**
|
||||
* Represents each string chunk to be indexed, a derivative of TextExtractor
|
||||
* file
|
||||
* A representation of a chunk of text from a file that can be used, when
|
||||
* supplied with an Ingester, to index the chunk for search.
|
||||
*/
|
||||
class AbstractFileChunk {
|
||||
final class AbstractFileChunk {
|
||||
|
||||
private int chunkID;
|
||||
private TextExtractor parent;
|
||||
private final int chunkNumber;
|
||||
private final TextExtractor textExtractor;
|
||||
|
||||
AbstractFileChunk(TextExtractor parent, int chunkID) {
|
||||
this.parent = parent;
|
||||
this.chunkID = chunkID;
|
||||
}
|
||||
|
||||
public TextExtractor getParent() {
|
||||
return parent;
|
||||
}
|
||||
|
||||
public int getChunkId() {
|
||||
return chunkID;
|
||||
/**
|
||||
* Constructs a representation of a chunk of text from a file that can be
|
||||
* used, when supplied with an Ingester, to index the chunk for search.
|
||||
*
|
||||
* @param textExtractor A TextExtractor for the file.
|
||||
* @param chunkNumber A sequence number for the chunk.
|
||||
*/
|
||||
AbstractFileChunk(TextExtractor textExtractor, int chunkNumber) {
|
||||
this.textExtractor = textExtractor;
|
||||
this.chunkNumber = chunkNumber;
|
||||
}
|
||||
|
||||
/**
|
||||
* return String representation of the absolute id (parent and child)
|
||||
* Gets the TextExtractor for the source file of the text chunk.
|
||||
*
|
||||
* @return
|
||||
* @return A reference to the TextExtractor.
|
||||
*/
|
||||
String getIdString() {
|
||||
return Server.getChunkIdString(this.parent.getSourceFile().getId(), this.chunkID);
|
||||
TextExtractor getTextExtractor() {
|
||||
return textExtractor;
|
||||
}
|
||||
|
||||
void index(Ingester ingester, byte[] content, long contentSize, Charset indexCharset) throws IngesterException {
|
||||
ByteContentStream bcs = new ByteContentStream(content, contentSize, parent.getSourceFile(), indexCharset);
|
||||
/**
|
||||
* Gets the sequence number of the text chunk.
|
||||
*
|
||||
* @return The chunk number.
|
||||
*/
|
||||
int getChunkNumber() {
|
||||
return chunkNumber;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the id of the text chunk.
|
||||
*
|
||||
* @return An id of the form [source file object id]_[chunk number]
|
||||
*/
|
||||
String getChunkId() {
|
||||
return Server.getChunkIdString(this.textExtractor.getSourceFile().getId(), this.chunkNumber);
|
||||
}
|
||||
|
||||
/**
|
||||
* Indexes the text chunk.
|
||||
*
|
||||
* @param ingester An Ingester to do the indexing.
|
||||
* @param chunkBytes The raw bytes of the text chunk.
|
||||
* @param chunkSize The size of the text chunk in bytes.
|
||||
* @param charSet The char set to use during indexing.
|
||||
*
|
||||
* @throws org.sleuthkit.autopsy.keywordsearch.Ingester.IngesterException
|
||||
*/
|
||||
void index(Ingester ingester, byte[] chunkBytes, long chunkSize, Charset charSet) throws IngesterException {
|
||||
ByteContentStream bcs = new ByteContentStream(chunkBytes, chunkSize, textExtractor.getSourceFile(), charSet);
|
||||
try {
|
||||
ingester.ingest(this, bcs, content.length);
|
||||
} catch (Exception ingEx) {
|
||||
throw new IngesterException(NbBundle.getMessage(this.getClass(), "AbstractFileChunk.index.exception.msg",
|
||||
parent.getSourceFile().getId(), chunkID), ingEx);
|
||||
ingester.ingest(this, bcs, chunkBytes.length);
|
||||
} catch (Exception ex) {
|
||||
throw new IngesterException(String.format("Error ingesting (indexing) file chunk: %s", getChunkId()), ex);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -1,7 +1,7 @@
|
||||
/*
|
||||
* Autopsy Forensic Browser
|
||||
*
|
||||
* Copyright 2011 Basis Technology Corp.
|
||||
* Copyright 2011-2016 Basis Technology Corp.
|
||||
* Contact: carrier <at> sleuthkit <dot> org
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
@ -25,7 +25,6 @@ import java.io.Reader;
|
||||
import java.nio.charset.Charset;
|
||||
|
||||
import org.openide.util.NbBundle;
|
||||
import org.sleuthkit.autopsy.coreutils.Logger;
|
||||
import org.apache.solr.common.util.ContentStream;
|
||||
import org.sleuthkit.datamodel.AbstractContent;
|
||||
import org.sleuthkit.datamodel.AbstractFile;
|
||||
@ -36,11 +35,10 @@ import org.sleuthkit.datamodel.AbstractFile;
|
||||
class AbstractFileStringContentStream implements ContentStream {
|
||||
//input
|
||||
|
||||
private AbstractFile content;
|
||||
private Charset charset;
|
||||
private final AbstractFile content;
|
||||
private final Charset charset;
|
||||
//converted
|
||||
private InputStream stream;
|
||||
private static Logger logger = Logger.getLogger(AbstractFileStringContentStream.class.getName());
|
||||
private final InputStream stream;
|
||||
|
||||
public AbstractFileStringContentStream(AbstractFile content, Charset charset, InputStream inputStream) {
|
||||
this.content = content;
|
||||
|
@ -157,7 +157,6 @@ DropdownSearchPanel.cutMenuItem.text=Cut
|
||||
DropdownSearchPanel.selectAllMenuItem.text=Select All
|
||||
DropdownSearchPanel.pasteMenuItem.text=Paste
|
||||
DropdownSearchPanel.copyMenuItem.text=Copy
|
||||
AbstractFileChunk.index.exception.msg=Problem ingesting file string chunk\: {0}, chunk\: {1}
|
||||
AbstractFileStringContentStream.getSize.exception.msg=Cannot tell how many chars in converted string, until entire string is converted
|
||||
AbstractFileStringContentStream.getSrcInfo.text=File\:{0}
|
||||
ByteContentStream.getSrcInfo.text=File\:{0}
|
||||
@ -187,7 +186,6 @@ Ingester.FscContentStream.getSrcInfo=File\:{0}
|
||||
Ingester.FscContentStream.getReader=Not supported yet.
|
||||
Ingester.NullContentStream.getSrcInfo.text=File\:{0}
|
||||
Ingester.NullContentStream.getReader=Not supported yet.
|
||||
Keyword.toString.text=Keyword'{'query\={0}, isLiteral\={1}, keywordType\={2}'}'
|
||||
KeywordSearch.moduleErr=Module Error
|
||||
KeywordSearch.fireNumIdxFileChg.moduleErr.msg=A module caused an error listening to KeywordSearch updates. See log to determine which module. Some data could be incomplete.
|
||||
KeywordSearchListsEncase.save.exception.msg=Not supported yet.
|
||||
|
@ -133,7 +133,6 @@ OptionsCategory_Keywords_KeywordSearchOptions=\u30ad\u30fc\u30ef\u30fc\u30c9\u69
|
||||
ExtractedContentPanel.pageOfLabel.text=of
|
||||
ExtractedContentPanel.pageCurLabel.text=-
|
||||
ExtractedContentPanel.pageTotalLabel.text=-
|
||||
AbstractFileChunk.index.exception.msg=\u30d5\u30a1\u30a4\u30eb\u30b9\u30c8\u30ea\u30f3\u30b0\u30c1\u30e3\u30f3\u30af\u306e\u30a4\u30f3\u30b8\u30a7\u30b9\u30c8\u4e2d\u306b\u554f\u984c\u304c\u767a\u751f\u3057\u307e\u3057\u305f\uff1a {0}, \u30c1\u30e3\u30f3\u30af\: {1}
|
||||
AbstractFileStringContentStream.getSize.exception.msg=\u30b9\u30c8\u30ea\u30f3\u30b0\u5168\u4f53\u304c\u5909\u63db\u3055\u308c\u306a\u3051\u308c\u3070\u3001\u5909\u63db\u3055\u308c\u305f\u30b9\u30c8\u30ea\u30f3\u30b0\u5185\u306e\u30ad\u30e3\u30e9\u30af\u30bf\u30fc\u6570\u306f\u4e0d\u660e\u3067\u3059\u3002
|
||||
AbstractFileStringContentStream.getSrcInfo.text=\u30d5\u30a1\u30a4\u30eb\uff1a{0}
|
||||
ByteContentStream.getSrcInfo.text=\u30d5\u30a1\u30a4\u30eb\uff1a{0}
|
||||
@ -208,7 +207,6 @@ KeywordSearchIngestModule.doInBackGround.pendingMsg=\uff08\u30da\u30f3\u30c7\u30
|
||||
SearchRunner.doInBackGround.cancelMsg=\uff08\u30ad\u30e3\u30f3\u30bb\u30eb\u4e2d\u2026\uff09
|
||||
Server.addDoc.exception.msg2=\u30a2\u30c3\u30d7\u30c7\u30fc\u30c8\u30cf\u30f3\u30c9\u30e9\u30fc\u3092\u4f7f\u7528\u3057\u307e\u3057\u305f\u304c\u3001\u30a4\u30f3\u30c7\u30c3\u30af\u30b9\u306b\u6b21\u306e\u30c9\u30ad\u30e5\u30e1\u30f3\u30c8\u3092\u8ffd\u52a0\u3067\u304d\u307e\u305b\u3093\u3067\u3057\u305f\uff1a{0}
|
||||
ExtractedContentViewer.getSolrContent.txtBodyItal=<span style\=''font-style\:italic''>{0}</span>
|
||||
Keyword.toString.text=Keyword'{'query\={0}, isLiteral\={1}, keywordType\={2}'}'
|
||||
KeywordSearchJobSettingsPanel.keywordSearchEncodings.text=-
|
||||
KeywordSearchJobSettingsPanel.languagesValLabel.text=-
|
||||
KeywordSearchJobSettingsPanel.encodingsLabel.text=\u30a8\u30f3\u30b3\u30fc\u30c7\u30a3\u30f3\u30b0\uff1a
|
||||
|
@ -562,8 +562,8 @@ class DropdownListSearchPanel extends KeywordSearchPanel {
|
||||
Boolean regex;
|
||||
|
||||
KeywordTableEntry(Keyword keyword) {
|
||||
this.name = keyword.getQuery();
|
||||
this.regex = !keyword.isLiteral();
|
||||
this.name = keyword.getSearchTerm();
|
||||
this.regex = !keyword.searchTermIsLiteral();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -1,7 +1,7 @@
|
||||
/*
|
||||
* Autopsy Forensic Browser
|
||||
*
|
||||
* Copyright 2014 Basis Technology Corp.
|
||||
* Copyright 2011-2016 Basis Technology Corp.
|
||||
* Contact: carrier <at> sleuthkit <dot> org
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
@ -18,7 +18,6 @@
|
||||
*/
|
||||
package org.sleuthkit.autopsy.keywordsearch;
|
||||
|
||||
import java.awt.*;
|
||||
import java.awt.event.ActionEvent;
|
||||
import java.awt.event.ActionListener;
|
||||
import java.awt.event.FocusEvent;
|
||||
@ -27,11 +26,15 @@ import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.logging.Level;
|
||||
import javax.swing.JMenuItem;
|
||||
|
||||
import org.sleuthkit.autopsy.coreutils.Logger;
|
||||
|
||||
/**
|
||||
* A simple UI for finding text after ingest
|
||||
* A dropdown panel that provides GUI components that allow a user to do three
|
||||
* types of ad hoc single keyword searches. The first option is a standard
|
||||
* Lucene query for one or more terms, with or without wildcards and explicit
|
||||
* Boolean operators, or a phrase. The second option is a Lucene query for a
|
||||
* substring of a single term. The third option is a regex query using first the
|
||||
* terms component, followed by standard Lucene queries for any terms found.
|
||||
*
|
||||
* The toolbar uses a different font from the rest of the application,
|
||||
* Monospaced 14, due to the necessity to find a font that displays both Arabic
|
||||
@ -39,48 +42,62 @@ import org.sleuthkit.autopsy.coreutils.Logger;
|
||||
* perform this task at the desired size, and neither could numerous other
|
||||
* fonts.
|
||||
*/
|
||||
public class DropdownSingleTermSearchPanel extends KeywordSearchPanel {
|
||||
public class DropdownSingleKeywordSearchPanel extends KeywordSearchPanel {
|
||||
|
||||
private static final Logger logger = Logger.getLogger(DropdownSingleTermSearchPanel.class.getName());
|
||||
private static DropdownSingleTermSearchPanel instance = null;
|
||||
private static final long serialVersionUID = 1L;
|
||||
private static final Logger LOGGER = Logger.getLogger(DropdownSingleKeywordSearchPanel.class.getName());
|
||||
private static DropdownSingleKeywordSearchPanel defaultInstance = null;
|
||||
|
||||
/**
|
||||
* Creates new form DropdownSingleTermSearchPanel
|
||||
* Gets the default instance of a dropdown panel that provides GUI
|
||||
* components that allow a user to do three types of ad hoc single keyword
|
||||
* searches.
|
||||
*/
|
||||
public DropdownSingleTermSearchPanel() {
|
||||
public static synchronized DropdownSingleKeywordSearchPanel getDefault() {
|
||||
if (null == defaultInstance) {
|
||||
defaultInstance = new DropdownSingleKeywordSearchPanel();
|
||||
}
|
||||
return defaultInstance;
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a dropdown panel that provides GUI components that allow a
|
||||
* user to do three types of ad hoc single keyword searches.
|
||||
*/
|
||||
public DropdownSingleKeywordSearchPanel() {
|
||||
initComponents();
|
||||
customizeComponents();
|
||||
}
|
||||
|
||||
/**
|
||||
* Does additional initialization of the GUI components created by the
|
||||
* initComponents method.
|
||||
*/
|
||||
private void customizeComponents() {
|
||||
keywordTextField.addFocusListener(new FocusListener() {
|
||||
@Override
|
||||
public void focusGained(FocusEvent e) {
|
||||
//do nothing
|
||||
}
|
||||
|
||||
@Override
|
||||
public void focusLost(FocusEvent e) {
|
||||
if (keywordTextField.getText().equals("")) {
|
||||
resetSearchBox();
|
||||
clearSearchBox();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
keywordTextField.setComponentPopupMenu(rightClickMenu);
|
||||
ActionListener actList = new ActionListener() {
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
JMenuItem jmi = (JMenuItem) e.getSource();
|
||||
if (jmi.equals(cutMenuItem)) {
|
||||
keywordTextField.cut();
|
||||
} else if (jmi.equals(copyMenuItem)) {
|
||||
keywordTextField.copy();
|
||||
} else if (jmi.equals(pasteMenuItem)) {
|
||||
keywordTextField.paste();
|
||||
} else if (jmi.equals(selectAllMenuItem)) {
|
||||
keywordTextField.selectAll();
|
||||
}
|
||||
ActionListener actList = (ActionEvent e) -> {
|
||||
JMenuItem jmi = (JMenuItem) e.getSource();
|
||||
if (jmi.equals(cutMenuItem)) {
|
||||
keywordTextField.cut();
|
||||
} else if (jmi.equals(copyMenuItem)) {
|
||||
keywordTextField.copy();
|
||||
} else if (jmi.equals(pasteMenuItem)) {
|
||||
keywordTextField.paste();
|
||||
} else if (jmi.equals(selectAllMenuItem)) {
|
||||
keywordTextField.selectAll();
|
||||
}
|
||||
};
|
||||
cutMenuItem.addActionListener(actList);
|
||||
@ -89,36 +106,43 @@ public class DropdownSingleTermSearchPanel extends KeywordSearchPanel {
|
||||
selectAllMenuItem.addActionListener(actList);
|
||||
}
|
||||
|
||||
public static synchronized DropdownSingleTermSearchPanel getDefault() {
|
||||
if (instance == null) {
|
||||
instance = new DropdownSingleTermSearchPanel();
|
||||
}
|
||||
return instance;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add an action listener to the Search buttom component of the panel.
|
||||
*
|
||||
* @param actionListener The actin listener.
|
||||
*/
|
||||
void addSearchButtonActionListener(ActionListener actionListener) {
|
||||
searchButton.addActionListener(actionListener);
|
||||
}
|
||||
|
||||
void resetSearchBox() {
|
||||
/**
|
||||
* Clears the text in the query text field, i.e., sets it to the emtpy
|
||||
* string.
|
||||
*/
|
||||
void clearSearchBox() {
|
||||
keywordTextField.setText("");
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a single keyword list consisting of a single keyword encapsulating
|
||||
* the input term(s)/phrase/substring/regex.
|
||||
*
|
||||
* @return The keyword list.
|
||||
*/
|
||||
@Override
|
||||
List<KeywordList> getKeywordLists() {
|
||||
List<Keyword> keywords = new ArrayList<>();
|
||||
keywords.add(new Keyword(keywordTextField.getText(),
|
||||
!regexRadioButton.isSelected(), exactRadioButton.isSelected()));
|
||||
|
||||
keywords.add(new Keyword(keywordTextField.getText(), !regexRadioButton.isSelected(), exactRadioButton.isSelected()));
|
||||
List<KeywordList> keywordLists = new ArrayList<>();
|
||||
keywordLists.add(new KeywordList(keywords));
|
||||
|
||||
return keywordLists;
|
||||
}
|
||||
|
||||
/**
|
||||
* Not implemented.
|
||||
*/
|
||||
@Override
|
||||
protected void postFilesIndexedChange() {
|
||||
//nothing to update
|
||||
}
|
||||
|
||||
/**
|
||||
@ -142,20 +166,20 @@ public class DropdownSingleTermSearchPanel extends KeywordSearchPanel {
|
||||
substringRadioButton = new javax.swing.JRadioButton();
|
||||
regexRadioButton = new javax.swing.JRadioButton();
|
||||
|
||||
org.openide.awt.Mnemonics.setLocalizedText(cutMenuItem, org.openide.util.NbBundle.getMessage(DropdownSingleTermSearchPanel.class, "DropdownSearchPanel.cutMenuItem.text")); // NOI18N
|
||||
org.openide.awt.Mnemonics.setLocalizedText(cutMenuItem, org.openide.util.NbBundle.getMessage(DropdownSingleKeywordSearchPanel.class, "DropdownSearchPanel.cutMenuItem.text")); // NOI18N
|
||||
rightClickMenu.add(cutMenuItem);
|
||||
|
||||
org.openide.awt.Mnemonics.setLocalizedText(copyMenuItem, org.openide.util.NbBundle.getMessage(DropdownSingleTermSearchPanel.class, "DropdownSearchPanel.copyMenuItem.text")); // NOI18N
|
||||
org.openide.awt.Mnemonics.setLocalizedText(copyMenuItem, org.openide.util.NbBundle.getMessage(DropdownSingleKeywordSearchPanel.class, "DropdownSearchPanel.copyMenuItem.text")); // NOI18N
|
||||
rightClickMenu.add(copyMenuItem);
|
||||
|
||||
org.openide.awt.Mnemonics.setLocalizedText(pasteMenuItem, org.openide.util.NbBundle.getMessage(DropdownSingleTermSearchPanel.class, "DropdownSearchPanel.pasteMenuItem.text")); // NOI18N
|
||||
org.openide.awt.Mnemonics.setLocalizedText(pasteMenuItem, org.openide.util.NbBundle.getMessage(DropdownSingleKeywordSearchPanel.class, "DropdownSearchPanel.pasteMenuItem.text")); // NOI18N
|
||||
rightClickMenu.add(pasteMenuItem);
|
||||
|
||||
org.openide.awt.Mnemonics.setLocalizedText(selectAllMenuItem, org.openide.util.NbBundle.getMessage(DropdownSingleTermSearchPanel.class, "DropdownSearchPanel.selectAllMenuItem.text")); // NOI18N
|
||||
org.openide.awt.Mnemonics.setLocalizedText(selectAllMenuItem, org.openide.util.NbBundle.getMessage(DropdownSingleKeywordSearchPanel.class, "DropdownSearchPanel.selectAllMenuItem.text")); // NOI18N
|
||||
rightClickMenu.add(selectAllMenuItem);
|
||||
|
||||
keywordTextField.setFont(new java.awt.Font("Monospaced", 0, 14)); // NOI18N NON-NLS
|
||||
keywordTextField.setText(org.openide.util.NbBundle.getMessage(DropdownSingleTermSearchPanel.class, "DropdownSearchPanel.keywordTextField.text")); // NOI18N
|
||||
keywordTextField.setFont(new java.awt.Font("Monospaced", 0, 14)); // NOI18N
|
||||
keywordTextField.setText(org.openide.util.NbBundle.getMessage(DropdownSingleKeywordSearchPanel.class, "DropdownSearchPanel.keywordTextField.text")); // NOI18N
|
||||
keywordTextField.setBorder(new javax.swing.border.LineBorder(new java.awt.Color(192, 192, 192), 1, true));
|
||||
keywordTextField.setMinimumSize(new java.awt.Dimension(2, 25));
|
||||
keywordTextField.setPreferredSize(new java.awt.Dimension(2, 25));
|
||||
@ -170,8 +194,8 @@ public class DropdownSingleTermSearchPanel extends KeywordSearchPanel {
|
||||
}
|
||||
});
|
||||
|
||||
searchButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/org/sleuthkit/autopsy/keywordsearch/search-icon.png"))); // NOI18N NON-NLS
|
||||
org.openide.awt.Mnemonics.setLocalizedText(searchButton, org.openide.util.NbBundle.getMessage(DropdownSingleTermSearchPanel.class, "DropdownSearchPanel.searchButton.text")); // NOI18N
|
||||
searchButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/org/sleuthkit/autopsy/keywordsearch/search-icon.png"))); // NOI18N
|
||||
org.openide.awt.Mnemonics.setLocalizedText(searchButton, org.openide.util.NbBundle.getMessage(DropdownSingleKeywordSearchPanel.class, "DropdownSearchPanel.searchButton.text")); // NOI18N
|
||||
searchButton.addActionListener(new java.awt.event.ActionListener() {
|
||||
public void actionPerformed(java.awt.event.ActionEvent evt) {
|
||||
searchButtonActionPerformed(evt);
|
||||
@ -180,13 +204,13 @@ public class DropdownSingleTermSearchPanel extends KeywordSearchPanel {
|
||||
|
||||
queryTypeButtonGroup.add(exactRadioButton);
|
||||
exactRadioButton.setSelected(true);
|
||||
org.openide.awt.Mnemonics.setLocalizedText(exactRadioButton, org.openide.util.NbBundle.getMessage(DropdownSingleTermSearchPanel.class, "DropdownSearchPanel.exactRadioButton.text")); // NOI18N
|
||||
org.openide.awt.Mnemonics.setLocalizedText(exactRadioButton, org.openide.util.NbBundle.getMessage(DropdownSingleKeywordSearchPanel.class, "DropdownSearchPanel.exactRadioButton.text")); // NOI18N
|
||||
|
||||
queryTypeButtonGroup.add(substringRadioButton);
|
||||
org.openide.awt.Mnemonics.setLocalizedText(substringRadioButton, org.openide.util.NbBundle.getMessage(DropdownSingleTermSearchPanel.class, "DropdownSearchPanel.substringRadioButton.text")); // NOI18N
|
||||
org.openide.awt.Mnemonics.setLocalizedText(substringRadioButton, org.openide.util.NbBundle.getMessage(DropdownSingleKeywordSearchPanel.class, "DropdownSearchPanel.substringRadioButton.text")); // NOI18N
|
||||
|
||||
queryTypeButtonGroup.add(regexRadioButton);
|
||||
org.openide.awt.Mnemonics.setLocalizedText(regexRadioButton, org.openide.util.NbBundle.getMessage(DropdownSingleTermSearchPanel.class, "DropdownSearchPanel.regexRadioButton.text")); // NOI18N
|
||||
org.openide.awt.Mnemonics.setLocalizedText(regexRadioButton, org.openide.util.NbBundle.getMessage(DropdownSingleKeywordSearchPanel.class, "DropdownSearchPanel.regexRadioButton.text")); // NOI18N
|
||||
|
||||
javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
|
||||
this.setLayout(layout);
|
||||
@ -224,18 +248,33 @@ public class DropdownSingleTermSearchPanel extends KeywordSearchPanel {
|
||||
);
|
||||
}// </editor-fold>//GEN-END:initComponents
|
||||
|
||||
/**
|
||||
* Action performed by the action listener for the search button.
|
||||
*
|
||||
* @param evt The action event.
|
||||
*/
|
||||
private void searchButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_searchButtonActionPerformed
|
||||
keywordTextFieldActionPerformed(evt);
|
||||
}//GEN-LAST:event_searchButtonActionPerformed
|
||||
|
||||
/**
|
||||
* Action performed by the action listener for the keyword text field.
|
||||
*
|
||||
* @param evt The action event.
|
||||
*/
|
||||
private void keywordTextFieldActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_keywordTextFieldActionPerformed
|
||||
try {
|
||||
search();
|
||||
} catch (Exception e) {
|
||||
logger.log(Level.SEVERE, "search() threw exception", e); //NON-NLS
|
||||
LOGGER.log(Level.SEVERE, "Error performing ad hoc single keyword search", e); //NON-NLS
|
||||
}
|
||||
}//GEN-LAST:event_keywordTextFieldActionPerformed
|
||||
|
||||
/**
|
||||
* Mouse event handler for the keyword text field.
|
||||
*
|
||||
* @param evt The mouse event.
|
||||
*/
|
||||
private void keywordTextFieldMouseClicked(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_keywordTextFieldMouseClicked
|
||||
if (evt.isPopupTrigger()) {
|
||||
rightClickMenu.show(evt.getComponent(), evt.getX(), evt.getY());
|
@ -1,26 +1,21 @@
|
||||
/*
|
||||
* Autopsy Forensic Browser
|
||||
*
|
||||
* Copyright 2011 Basis Technology Corp.
|
||||
*
|
||||
* Copyright 2003-2016 Basis Technology Corp.
|
||||
* Contact: carrier <at> sleuthkit <dot> org
|
||||
*
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
/*
|
||||
* DropdownToolbar
|
||||
*
|
||||
*/
|
||||
package org.sleuthkit.autopsy.keywordsearch;
|
||||
|
||||
import java.awt.event.ActionEvent;
|
||||
@ -37,22 +32,26 @@ import org.sleuthkit.autopsy.casemodule.Case;
|
||||
import org.sleuthkit.autopsy.core.RuntimeProperties;
|
||||
|
||||
/**
|
||||
* Keyword search tool bar (in upper right, by default) with drop down panels
|
||||
* for ad hoc searches by list or expression.
|
||||
* A panel that provides a toolbar button for the dropdown keyword list search
|
||||
* panel and dropdown single keyword search panel. Displayed in the upper right
|
||||
* hand corner of the application by default.
|
||||
*/
|
||||
class DropdownToolbar extends javax.swing.JPanel {
|
||||
|
||||
private static final Logger logger = Logger.getLogger(DropdownToolbar.class.getName());
|
||||
private KeywordPropertyChangeListener listener;
|
||||
private boolean active = false;
|
||||
private static final long serialVersionUID = 1L;
|
||||
private static final Logger LOGGER = Logger.getLogger(DropdownToolbar.class.getName());
|
||||
private static DropdownToolbar instance;
|
||||
private DropdownSingleTermSearchPanel dropPanel = null;
|
||||
|
||||
private DropdownToolbar() {
|
||||
initComponents();
|
||||
customizeComponents();
|
||||
}
|
||||
private SearchSettingsChangeListener searchSettingsChangeListener;
|
||||
private boolean active = false;
|
||||
private DropdownSingleKeywordSearchPanel dropPanel = null;
|
||||
|
||||
/**
|
||||
* Gets the singleton panel that provides a toolbar button for the dropdown
|
||||
* keyword list search panel and dropdown single keyword search panel.
|
||||
* Displayed in the upper right hand corner of the application by default.
|
||||
*
|
||||
* @return The panel.
|
||||
*/
|
||||
public synchronized static DropdownToolbar getDefault() {
|
||||
if (instance == null) {
|
||||
instance = new DropdownToolbar();
|
||||
@ -60,18 +59,30 @@ class DropdownToolbar extends javax.swing.JPanel {
|
||||
return instance;
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a panel that provides a toolbar button for the dropdown
|
||||
* keyword list search panel and dropdown single keyword search panel.
|
||||
* Displayed in the upper right hand corner of the application by default.
|
||||
*/
|
||||
private DropdownToolbar() {
|
||||
initComponents();
|
||||
customizeComponents();
|
||||
}
|
||||
|
||||
/**
|
||||
* Does additional initialization of the GUI components created by the
|
||||
* initComponents method.
|
||||
*/
|
||||
private void customizeComponents() {
|
||||
listener = new KeywordPropertyChangeListener();
|
||||
KeywordSearch.getServer().addServerActionListener(listener);
|
||||
Case.addPropertyChangeListener(listener);
|
||||
searchSettingsChangeListener = new SearchSettingsChangeListener();
|
||||
KeywordSearch.getServer().addServerActionListener(searchSettingsChangeListener);
|
||||
Case.addPropertyChangeListener(searchSettingsChangeListener);
|
||||
|
||||
DropdownListSearchPanel listsPanel = DropdownListSearchPanel.getDefault();
|
||||
listsPanel.addSearchButtonActionListener(new ActionListener() {
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
listsMenu.setVisible(false);
|
||||
}
|
||||
listsPanel.addSearchButtonActionListener((ActionEvent e) -> {
|
||||
listsMenu.setVisible(false);
|
||||
});
|
||||
|
||||
// Adding border of six to account for menu border
|
||||
listsMenu.setSize(listsPanel.getPreferredSize().width + 6, listsPanel.getPreferredSize().height + 6);
|
||||
listsMenu.add(listsPanel);
|
||||
@ -92,7 +103,7 @@ class DropdownToolbar extends javax.swing.JPanel {
|
||||
}
|
||||
});
|
||||
|
||||
dropPanel = DropdownSingleTermSearchPanel.getDefault();
|
||||
dropPanel = DropdownSingleKeywordSearchPanel.getDefault();
|
||||
dropPanel.addSearchButtonActionListener(new ActionListener() {
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
@ -120,6 +131,27 @@ class DropdownToolbar extends javax.swing.JPanel {
|
||||
|
||||
}
|
||||
|
||||
private void maybeShowListsPopup(MouseEvent evt) {
|
||||
if (!active) {
|
||||
return;
|
||||
}
|
||||
if (evt != null && !SwingUtilities.isLeftMouseButton(evt)) {
|
||||
return;
|
||||
}
|
||||
listsMenu.show(listsButton, listsButton.getWidth() - listsMenu.getWidth(), listsButton.getHeight() - 1);
|
||||
}
|
||||
|
||||
private void maybeShowSearchPopup(MouseEvent evt) {
|
||||
if (!active) {
|
||||
return;
|
||||
}
|
||||
if (evt != null && !SwingUtilities.isLeftMouseButton(evt)) {
|
||||
return;
|
||||
}
|
||||
searchMenu.show(searchDropButton, searchDropButton.getWidth() - searchMenu.getWidth(), searchDropButton.getHeight() - 1);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 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
|
||||
@ -216,13 +248,13 @@ class DropdownToolbar extends javax.swing.JPanel {
|
||||
private javax.swing.JPopupMenu searchMenu;
|
||||
// End of variables declaration//GEN-END:variables
|
||||
|
||||
private class KeywordPropertyChangeListener implements PropertyChangeListener {
|
||||
private class SearchSettingsChangeListener implements PropertyChangeListener {
|
||||
|
||||
@Override
|
||||
public void propertyChange(PropertyChangeEvent evt) {
|
||||
String changed = evt.getPropertyName();
|
||||
if (changed.equals(Case.Events.CURRENT_CASE.toString())) {
|
||||
dropPanel.resetSearchBox();
|
||||
dropPanel.clearSearchBox();
|
||||
setFields(null != evt.getNewValue() && RuntimeProperties.coreComponentsAreActive());
|
||||
} else if (changed.equals(Server.CORE_EVT)) {
|
||||
final Server.CORE_EVT_STATES state = (Server.CORE_EVT_STATES) evt.getNewValue();
|
||||
@ -232,9 +264,9 @@ class DropdownToolbar extends javax.swing.JPanel {
|
||||
final int numIndexedFiles = KeywordSearch.getServer().queryNumIndexedFiles();
|
||||
KeywordSearch.fireNumIndexedFilesChange(null, numIndexedFiles);
|
||||
} catch (NoOpenCoreException ex) {
|
||||
logger.log(Level.SEVERE, "Error executing Solr query, {0}", ex); //NON-NLS
|
||||
LOGGER.log(Level.SEVERE, "Error executing Solr query, {0}", ex); //NON-NLS
|
||||
} catch (KeywordSearchModuleException se) {
|
||||
logger.log(Level.SEVERE, "Error executing Solr query, {0}", se.getMessage()); //NON-NLS
|
||||
LOGGER.log(Level.SEVERE, "Error executing Solr query, {0}", se.getMessage()); //NON-NLS
|
||||
}
|
||||
break;
|
||||
case STOPPED:
|
||||
@ -251,23 +283,4 @@ class DropdownToolbar extends javax.swing.JPanel {
|
||||
}
|
||||
}
|
||||
|
||||
private void maybeShowListsPopup(MouseEvent evt) {
|
||||
if (!active) {
|
||||
return;
|
||||
}
|
||||
if (evt != null && !SwingUtilities.isLeftMouseButton(evt)) {
|
||||
return;
|
||||
}
|
||||
listsMenu.show(listsButton, listsButton.getWidth() - listsMenu.getWidth(), listsButton.getHeight() - 1);
|
||||
}
|
||||
|
||||
private void maybeShowSearchPopup(MouseEvent evt) {
|
||||
if (!active) {
|
||||
return;
|
||||
}
|
||||
if (evt != null && !SwingUtilities.isLeftMouseButton(evt)) {
|
||||
return;
|
||||
}
|
||||
searchMenu.show(searchDropButton, searchDropButton.getWidth() - searchMenu.getWidth(), searchDropButton.getHeight() - 1);
|
||||
}
|
||||
}
|
||||
|
@ -100,7 +100,7 @@ class GlobalEditListPanel extends javax.swing.JPanel implements ListSelectionLis
|
||||
lsm.addListSelectionListener(new ListSelectionListener() {
|
||||
@Override
|
||||
public void valueChanged(ListSelectionEvent e) {
|
||||
if (lsm.isSelectionEmpty() || currentKeywordList.isLocked() || IngestManager.getInstance().isIngestRunning()) {
|
||||
if (lsm.isSelectionEmpty() || currentKeywordList.isEditable() || IngestManager.getInstance().isIngestRunning()) {
|
||||
deleteWordButton.setEnabled(false);
|
||||
} else {
|
||||
deleteWordButton.setEnabled(true);
|
||||
@ -140,7 +140,7 @@ class GlobalEditListPanel extends javax.swing.JPanel implements ListSelectionLis
|
||||
listOptionsSeparator.setEnabled(canEditList);
|
||||
|
||||
// items that need an unlocked list w/out ingest running
|
||||
boolean isListLocked = ((isListSelected == false) || (currentKeywordList.isLocked()));
|
||||
boolean isListLocked = ((isListSelected == false) || (currentKeywordList.isEditable()));
|
||||
boolean canAddWord = isListSelected && !isIngestRunning && !isListLocked;
|
||||
newWordButton.setEnabled(canAddWord);
|
||||
keywordOptionsLabel.setEnabled(canAddWord);
|
||||
@ -581,10 +581,10 @@ class GlobalEditListPanel extends javax.swing.JPanel implements ListSelectionLis
|
||||
Keyword word = currentKeywordList.getKeywords().get(rowIndex);
|
||||
switch (columnIndex) {
|
||||
case 0:
|
||||
ret = (Object) word.getQuery();
|
||||
ret = (Object) word.getSearchTerm();
|
||||
break;
|
||||
case 1:
|
||||
ret = (Object) !word.isLiteral();
|
||||
ret = (Object) !word.searchTermIsLiteral();
|
||||
break;
|
||||
default:
|
||||
logger.log(Level.SEVERE, "Invalid table column index: {0}", columnIndex); //NON-NLS
|
||||
|
@ -82,7 +82,7 @@ final class GlobalListSettingsPanel extends javax.swing.JPanel implements Option
|
||||
}
|
||||
|
||||
XmlKeywordSearchList writer = XmlKeywordSearchList.getCurrent();
|
||||
if (writer.listExists(listName) && writer.getList(listName).isLocked()) {
|
||||
if (writer.listExists(listName) && writer.getList(listName).isEditable()) {
|
||||
KeywordSearchUtil.displayDialog(FEATURE_NAME, NbBundle.getMessage(this.getClass(), "KeywordSearchConfigurationPanel1.customizeComponents.noOwDefaultMsg"), KeywordSearchUtil.DIALOG_MESSAGE_TYPE.WARN);
|
||||
return;
|
||||
}
|
||||
|
@ -176,7 +176,7 @@ class GlobalListsManagementPanel extends javax.swing.JPanel implements OptionsPa
|
||||
}
|
||||
boolean shouldAdd = false;
|
||||
if (writer.listExists(listName)) {
|
||||
if (writer.getList(listName).isLocked()) {
|
||||
if (writer.getList(listName).isEditable()) {
|
||||
boolean replace = KeywordSearchUtil.displayConfirmDialog(
|
||||
NbBundle.getMessage(this.getClass(), "KeywordSearch.newKeywordListMsg"),
|
||||
NbBundle.getMessage(this.getClass(), "KeywordSearchListsManagementPanel.newKeywordListDescription", listName),
|
||||
|
@ -1,7 +1,7 @@
|
||||
/*
|
||||
* Autopsy Forensic Browser
|
||||
*
|
||||
* Copyright 2011-2015 Basis Technology Corp.
|
||||
* Copyright 2011-2016 Basis Technology Corp.
|
||||
* Contact: carrier <at> sleuthkit <dot> org
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
@ -59,7 +59,7 @@ class Ingester {
|
||||
//for ingesting chunk as SolrInputDocument (non-content-streaming, by-pass tika)
|
||||
//TODO use a streaming way to add content to /update handler
|
||||
private static final int MAX_DOC_CHUNK_SIZE = 1024 * 1024;
|
||||
private static final String docContentEncoding = "UTF-8"; //NON-NLS
|
||||
private static final String ENCODING = "UTF-8"; //NON-NLS
|
||||
|
||||
private Ingester() {
|
||||
}
|
||||
@ -134,7 +134,7 @@ class Ingester {
|
||||
|
||||
//overwrite id with the chunk id
|
||||
params.put(Server.Schema.ID.toString(),
|
||||
Server.getChunkIdString(sourceContent.getId(), fec.getChunkId()));
|
||||
Server.getChunkIdString(sourceContent.getId(), fec.getChunkNumber()));
|
||||
|
||||
ingest(bcs, params, size);
|
||||
}
|
||||
@ -298,7 +298,7 @@ class Ingester {
|
||||
if (read != 0) {
|
||||
String s = "";
|
||||
try {
|
||||
s = new String(docChunkContentBuf, 0, read, docContentEncoding);
|
||||
s = new String(docChunkContentBuf, 0, read, ENCODING);
|
||||
// Sanitize by replacing non-UTF-8 characters with caret '^' before adding to index
|
||||
char[] chars = null;
|
||||
for (int i = 0; i < s.length(); i++) {
|
||||
|
@ -1,7 +1,7 @@
|
||||
/*
|
||||
* Autopsy Forensic Browser
|
||||
*
|
||||
* Copyright 2011-2014 Basis Technology Corp.
|
||||
* Copyright 2011-2016 Basis Technology Corp.
|
||||
* Contact: carrier <at> sleuthkit <dot> org
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
@ -18,81 +18,136 @@
|
||||
*/
|
||||
package org.sleuthkit.autopsy.keywordsearch;
|
||||
|
||||
import org.openide.util.NbBundle;
|
||||
import org.sleuthkit.datamodel.BlackboardAttribute;
|
||||
|
||||
/**
|
||||
* Representation of single keyword to search for
|
||||
* A representation of a keyword for which to search. The search term for the
|
||||
* keyword may be either a literal term, to be treated as either a whole word or
|
||||
* a substring, or a regex.
|
||||
*
|
||||
* It is currently possible to optionally associate an artifact attribute type
|
||||
* with a keyword. This feature was added to support an initial implementation
|
||||
* of account number search and may be removed in the future.
|
||||
*/
|
||||
class Keyword {
|
||||
|
||||
private String keywordString; // keyword to search for
|
||||
private boolean isLiteral; // false if reg exp
|
||||
private boolean isWholeword; // false if match a substring
|
||||
private BlackboardAttribute.ATTRIBUTE_TYPE keywordType = null;
|
||||
private String searchTerm;
|
||||
private boolean isLiteral;
|
||||
private boolean isWholeWord;
|
||||
private BlackboardAttribute.ATTRIBUTE_TYPE artifactAtrributeType;
|
||||
|
||||
/**
|
||||
* Constructs a representation of a keyword for which to search. The search
|
||||
* term for the keyword may be either a literal term that will be treated as
|
||||
* a whole word, or a regex.
|
||||
*
|
||||
* @param query Keyword to search for
|
||||
* @param isLiteral false if reg exp
|
||||
* @param searchTerm The search term for the keyword.
|
||||
* @param isLiteral Whether or not the search term is a literal term that
|
||||
* will be treated as a whole word, instead of a regex.
|
||||
*/
|
||||
Keyword(String query, boolean isLiteral) {
|
||||
this.keywordString = query;
|
||||
Keyword(String searchTerm, boolean isLiteral) {
|
||||
this.searchTerm = searchTerm;
|
||||
this.isLiteral = isLiteral;
|
||||
this.isWholeword = true;
|
||||
this.isWholeWord = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a representation of a keyword for which to search. The search
|
||||
* term may be either a literal term, to be treated as either a whole word
|
||||
* or as a substring, or a regex.
|
||||
*
|
||||
* @param query Keyword to search for
|
||||
* @param isLiteral false if reg exp
|
||||
* @param isWholeword false to match substring (undefined behavior if regexp
|
||||
* is true)
|
||||
* @param searchTerm The search term.
|
||||
* @param isLiteral Whether or not the search term is a literal term,
|
||||
* instead of a regex.
|
||||
* @param isWholeWord Whether or not the search term, if it is a literal
|
||||
* search term, should be treated as a whole word rather
|
||||
* than a substring.
|
||||
*/
|
||||
Keyword(String query, boolean isLiteral, boolean isWholeword) {
|
||||
this.keywordString = query;
|
||||
Keyword(String searchTerm, boolean isLiteral, boolean isWholeWord) {
|
||||
this.searchTerm = searchTerm;
|
||||
this.isLiteral = isLiteral;
|
||||
this.isWholeword = isWholeword;
|
||||
this.isWholeWord = isWholeWord;
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a representation of a keyword for which to search, for the
|
||||
* purpose of finding a specific artifact attribute. The search term may be
|
||||
* either a literal term, to be treated as a whole word, or a regex.
|
||||
*
|
||||
* @param query Keyword to search for
|
||||
* @param isLiteral false if reg exp
|
||||
* @param keywordType
|
||||
* The association of an artifact attribute type with a keyword was added to
|
||||
* support an initial implementation of account number search and may be
|
||||
* removed in the future.
|
||||
*
|
||||
* @param searchTerm The search term.
|
||||
* @param isLiteral Whether or not the search term is a literal term, to
|
||||
* be treated as a whole word, instead of a regex.
|
||||
* @param keywordType The artifact attribute type.
|
||||
*/
|
||||
Keyword(String query, boolean isLiteral, BlackboardAttribute.ATTRIBUTE_TYPE keywordType) {
|
||||
this(query, isLiteral);
|
||||
this.keywordType = keywordType;
|
||||
}
|
||||
|
||||
void setType(BlackboardAttribute.ATTRIBUTE_TYPE keywordType) {
|
||||
this.keywordType = keywordType;
|
||||
}
|
||||
|
||||
BlackboardAttribute.ATTRIBUTE_TYPE getType() {
|
||||
return this.keywordType;
|
||||
Keyword(String searchTerm, boolean isLiteral, BlackboardAttribute.ATTRIBUTE_TYPE artifactAtrributeType) {
|
||||
this(searchTerm, isLiteral);
|
||||
this.artifactAtrributeType = artifactAtrributeType;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the search term for the keyword, which may be either a literal term
|
||||
* or a regex.
|
||||
*
|
||||
* @return Keyword to search for
|
||||
* @return The search term.
|
||||
*/
|
||||
String getQuery() {
|
||||
return keywordString;
|
||||
String getSearchTerm() {
|
||||
return searchTerm;
|
||||
}
|
||||
|
||||
boolean isLiteral() {
|
||||
/**
|
||||
* Indicates whether the search term for the keyword is a literal term or a
|
||||
* regex.
|
||||
*
|
||||
* @return True or false.
|
||||
*/
|
||||
boolean searchTermIsLiteral() {
|
||||
return isLiteral;
|
||||
}
|
||||
|
||||
boolean isWholeword() {
|
||||
return isWholeword;
|
||||
/**
|
||||
* Indicates whether or not the search term for the keyword, if it is a
|
||||
* literal term and not a regex, will be treated as a whole word or as a
|
||||
* substring.
|
||||
*
|
||||
* @return True or false.
|
||||
*/
|
||||
boolean searchTermIsWholeWord() {
|
||||
return isWholeWord;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the artifact attribute type associated with the keyword, if any.
|
||||
*
|
||||
* The association of an artifact attribute type with the keyword was added
|
||||
* to support an initial implementation of account number search and may be
|
||||
* removed in the future.
|
||||
*
|
||||
* @param artifactAtrributeType
|
||||
*/
|
||||
void setArtifactAttributeType(BlackboardAttribute.ATTRIBUTE_TYPE artifactAtrributeType) {
|
||||
this.artifactAtrributeType = artifactAtrributeType;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the artifact attribute type associated with the keyword, if any.
|
||||
*
|
||||
* The association of an artifact attribute type with the keyword was added
|
||||
* to support an initial implementation of account number search and may be
|
||||
* removed in the future.
|
||||
*
|
||||
* @return A attribute type object or null.
|
||||
*/
|
||||
BlackboardAttribute.ATTRIBUTE_TYPE getArtifactAttributeType() {
|
||||
return this.artifactAtrributeType;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return NbBundle.getMessage(this.getClass(), "Keyword.toString.text", keywordString, isLiteral, keywordType);
|
||||
return String.format("Keyword{searchTerm='%s', isLiteral=%s, isWholeWord=%s}", searchTerm, isLiteral, isWholeWord);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -103,21 +158,19 @@ class Keyword {
|
||||
if (getClass() != obj.getClass()) {
|
||||
return false;
|
||||
}
|
||||
final Keyword other = (Keyword) obj;
|
||||
if ((this.keywordString == null) ? (other.keywordString != null) : !this.keywordString.equals(other.keywordString)) {
|
||||
return false;
|
||||
}
|
||||
if (this.isLiteral != other.isLiteral) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
Keyword other = (Keyword) obj;
|
||||
return (this.searchTerm.equals(other.searchTerm)
|
||||
&& this.isLiteral == other.isLiteral
|
||||
&& this.isWholeWord == other.isWholeWord);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int hash = 7;
|
||||
hash = 17 * hash + (this.keywordString != null ? this.keywordString.hashCode() : 0);
|
||||
hash = 17 * hash + this.searchTerm.hashCode();
|
||||
hash = 17 * hash + (this.isLiteral ? 1 : 0);
|
||||
hash = 17 * hash + (this.isWholeWord ? 1 : 0);
|
||||
return hash;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -1,15 +1,15 @@
|
||||
/*
|
||||
* Autopsy Forensic Browser
|
||||
*
|
||||
* Copyright 2011-2014 Basis Technology Corp.
|
||||
*
|
||||
* Copyright 2011-2016 Basis Technology Corp.
|
||||
* Contact: carrier <at> sleuthkit <dot> org
|
||||
*
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* 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.
|
||||
@ -21,32 +21,75 @@ package org.sleuthkit.autopsy.keywordsearch;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* A list of keywords for which to search. Includes list creation and
|
||||
* modification metadata and settings that determine how the list is to be used
|
||||
* when ingesting a data source. Standard lists provided by Autopsy may be
|
||||
* marked as not editable.
|
||||
*/
|
||||
public class KeywordList {
|
||||
|
||||
private String name;
|
||||
private Date created;
|
||||
private Date modified;
|
||||
private Boolean useForIngest;
|
||||
private Boolean ingestMessages;
|
||||
private Boolean postIngestMessages;
|
||||
private List<Keyword> keywords;
|
||||
private Boolean locked;
|
||||
private Boolean isEditable;
|
||||
|
||||
KeywordList(String name, Date created, Date modified, Boolean useForIngest, Boolean ingestMessages, List<Keyword> keywords, boolean locked) {
|
||||
/**
|
||||
* Constructs a list of keywords for which to search. Includes list creation
|
||||
* and modification metadata and settings that determine how the list is to
|
||||
* be used when ingesting a data source. Standard lists provided by Autopsy
|
||||
* may be marked as not editable.
|
||||
*
|
||||
* @param name The name to asociate with the list.
|
||||
* @param created When the list was created.
|
||||
* @param modified When the list was last modified.
|
||||
* @param useForIngest Whether or not the list is to be used when
|
||||
* ingesting a data source.
|
||||
* @param postIngestMessages Whether or not to post ingest inbox messages
|
||||
* when a keyword within the list is found while
|
||||
* ingesting a data source.
|
||||
* @param keywords The keywords that make up the list.
|
||||
* @param isEditable Whether or not the list may be edited by a
|
||||
* user; standard lists provided by Autopsy should
|
||||
* not be edited.
|
||||
*/
|
||||
KeywordList(String name, Date created, Date modified, Boolean useForIngest, Boolean postIngestMessages, List<Keyword> keywords, boolean isEditable) {
|
||||
this.name = name;
|
||||
this.created = created;
|
||||
this.modified = modified;
|
||||
this.useForIngest = useForIngest;
|
||||
this.ingestMessages = ingestMessages;
|
||||
this.postIngestMessages = postIngestMessages;
|
||||
this.keywords = keywords;
|
||||
this.locked = locked;
|
||||
this.isEditable = isEditable;
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a list of keywords for which to search. Includes list creation
|
||||
* and modification metadata and settings that determine how the list is to
|
||||
* be used when ingesting a data source. The list will be marked as a
|
||||
* standard lists provided by Autopsy that should not be treated as
|
||||
* editable.
|
||||
*
|
||||
* @param name The name to asociate with the list.
|
||||
* @param created When the list was created.
|
||||
* @param modified When the list was last modified.
|
||||
* @param useForIngest Whether or not the list is to be used when
|
||||
* ingesting a data source.
|
||||
* @param postIngestMessages Whether or not to post ingest inbox messages
|
||||
* when a keyword within the list is found while
|
||||
* ingesting a data source.
|
||||
* @param keywords The keywords that make up the list.
|
||||
*/
|
||||
KeywordList(String name, Date created, Date modified, Boolean useForIngest, Boolean ingestMessages, List<Keyword> keywords) {
|
||||
this(name, created, modified, useForIngest, ingestMessages, keywords, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create an unnamed list. Usually used for ad-hoc searches
|
||||
* Constructs a temporary list of keywords to be used for ad hoc keyword
|
||||
* search and then discarded.
|
||||
*
|
||||
* @param keywords
|
||||
*/
|
||||
@ -54,74 +97,116 @@ public class KeywordList {
|
||||
this("", new Date(0), new Date(0), false, false, keywords, false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (obj == null) {
|
||||
return false;
|
||||
}
|
||||
if (getClass() != obj.getClass()) {
|
||||
return false;
|
||||
}
|
||||
final KeywordList other = (KeywordList) obj;
|
||||
if ((this.name == null) ? (other.name != null) : !this.name.equals(other.name)) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int hash = 5;
|
||||
return hash;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the name assigned to the keyword list.
|
||||
*
|
||||
* @return The list name.
|
||||
*/
|
||||
String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the date the keyword list was created.
|
||||
*
|
||||
* @return The date.
|
||||
*/
|
||||
Date getDateCreated() {
|
||||
return created;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the date the keyword list was last modified.
|
||||
*
|
||||
* @return The date.
|
||||
*/
|
||||
Date getDateModified() {
|
||||
return modified;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets whether or not the list should be used when ingesting a data source.
|
||||
*
|
||||
* @return True or false.
|
||||
*/
|
||||
Boolean getUseForIngest() {
|
||||
return useForIngest;
|
||||
}
|
||||
|
||||
void setUseForIngest(boolean use) {
|
||||
this.useForIngest = use;
|
||||
/**
|
||||
* Sets whether or not the list should be used when ingesting a data source.
|
||||
*
|
||||
* @param useForIngest True or false.
|
||||
*/
|
||||
void setUseForIngest(boolean useForIngest) {
|
||||
this.useForIngest = useForIngest;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets whether or not to post ingest inbox messages when a keyword within
|
||||
* the list is found while ingesting a data source.
|
||||
*
|
||||
* @return true or false
|
||||
*/
|
||||
Boolean getIngestMessages() {
|
||||
return ingestMessages;
|
||||
return postIngestMessages;
|
||||
}
|
||||
|
||||
void setIngestMessages(boolean ingestMessages) {
|
||||
this.ingestMessages = ingestMessages;
|
||||
/**
|
||||
* Sets whether or not to post ingest inbox messages when a keyword within
|
||||
* the list is found while ingesting a data source.
|
||||
*
|
||||
* @param postIngestMessages True or false.
|
||||
*/
|
||||
void setIngestMessages(boolean postIngestMessages) {
|
||||
this.postIngestMessages = postIngestMessages;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the keywords included in the list
|
||||
*
|
||||
* @return A colleciton of Keyword objects.
|
||||
*/
|
||||
List<Keyword> getKeywords() {
|
||||
return keywords;
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicates whether or not a given keyword is included in the list.
|
||||
*
|
||||
* @param keyword The keyword of interest.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
boolean hasKeyword(Keyword keyword) {
|
||||
return keywords.contains(keyword);
|
||||
}
|
||||
|
||||
boolean hasKeyword(String keyword) {
|
||||
//note, this ignores isLiteral
|
||||
for (Keyword k : keywords) {
|
||||
if (k.getQuery().equals(keyword)) {
|
||||
/**
|
||||
* Indicates whether or not a given search term is included in the list.
|
||||
*
|
||||
* @param searchTerm The search term.
|
||||
*
|
||||
* @return True or false.
|
||||
*/
|
||||
boolean hasSearchTerm(String searchTerm) {
|
||||
for (Keyword word : keywords) {
|
||||
if (word.getSearchTerm().equals(searchTerm)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
Boolean isLocked() {
|
||||
return locked;
|
||||
/**
|
||||
* Indicates Whether or not the list should be editable by a user; standard
|
||||
* lists provided by Autopsy should be marked as not editable when they are
|
||||
* contructed.
|
||||
*
|
||||
* @return True or false.
|
||||
*/
|
||||
Boolean isEditable() {
|
||||
return isEditable;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -124,7 +124,7 @@ abstract class KeywordSearchList {
|
||||
List<Keyword> ccns = new ArrayList<>();
|
||||
ccns.add(new Keyword(CCN_REGEX, false, BlackboardAttribute.ATTRIBUTE_TYPE.TSK_CARD_NUMBER));
|
||||
lockedLists.add("Credit Card Numbers");
|
||||
addList("Credit Card Numbers", ccns, true, false, true);
|
||||
addList("Credit Card Numbers", ccns, false, false, true);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -141,7 +141,7 @@ abstract class KeywordSearchList {
|
||||
//we want to preserve state of locked lists
|
||||
List<String> toClear = new ArrayList<>();
|
||||
for (String list : theLists.keySet()) {
|
||||
if (theLists.get(list).isLocked() == false) {
|
||||
if (theLists.get(list).isEditable() == false) {
|
||||
toClear.add(list);
|
||||
}
|
||||
}
|
||||
@ -173,7 +173,7 @@ abstract class KeywordSearchList {
|
||||
public List<KeywordList> getListsL(boolean locked) {
|
||||
List<KeywordList> ret = new ArrayList<>();
|
||||
for (KeywordList list : theLists.values()) {
|
||||
if (list.isLocked().equals(locked)) {
|
||||
if (list.isEditable().equals(locked)) {
|
||||
ret.add(list);
|
||||
}
|
||||
}
|
||||
@ -200,7 +200,7 @@ abstract class KeywordSearchList {
|
||||
ArrayList<String> lists = new ArrayList<>();
|
||||
for (String listName : theLists.keySet()) {
|
||||
KeywordList list = theLists.get(listName);
|
||||
if (locked == list.isLocked()) {
|
||||
if (locked == list.isEditable()) {
|
||||
lists.add(listName);
|
||||
}
|
||||
}
|
||||
@ -218,7 +218,7 @@ abstract class KeywordSearchList {
|
||||
public KeywordList getListWithKeyword(String keyword) {
|
||||
KeywordList found = null;
|
||||
for (KeywordList list : theLists.values()) {
|
||||
if (list.hasKeyword(keyword)) {
|
||||
if (list.hasSearchTerm(keyword)) {
|
||||
found = list;
|
||||
break;
|
||||
}
|
||||
@ -246,7 +246,7 @@ abstract class KeywordSearchList {
|
||||
int numLists = 0;
|
||||
for (String listName : theLists.keySet()) {
|
||||
KeywordList list = theLists.get(listName);
|
||||
if (locked == list.isLocked()) {
|
||||
if (locked == list.isEditable()) {
|
||||
++numLists;
|
||||
}
|
||||
}
|
||||
@ -330,7 +330,7 @@ abstract class KeywordSearchList {
|
||||
}
|
||||
|
||||
boolean addList(KeywordList list) {
|
||||
return addList(list.getName(), list.getKeywords(), list.getUseForIngest(), list.getIngestMessages(), list.isLocked());
|
||||
return addList(list.getName(), list.getKeywords(), list.getUseForIngest(), list.getIngestMessages(), list.isEditable());
|
||||
}
|
||||
|
||||
/**
|
||||
@ -437,7 +437,7 @@ abstract class KeywordSearchList {
|
||||
*/
|
||||
boolean deleteList(String name) {
|
||||
KeywordList delList = getList(name);
|
||||
if (delList != null && !delList.isLocked()) {
|
||||
if (delList != null && !delList.isEditable()) {
|
||||
theLists.remove(name);
|
||||
}
|
||||
|
||||
|
@ -39,7 +39,7 @@ import org.sleuthkit.autopsy.ingest.IngestModuleGlobalSettingsPanel;
|
||||
@ServiceProvider(service = IngestModuleFactory.class)
|
||||
public class KeywordSearchModuleFactory extends IngestModuleFactoryAdapter {
|
||||
|
||||
private static final HashSet<String> defaultDisabledKeywordListNames = new HashSet<>(Arrays.asList("Phone Numbers", "IP Addresses", "URLs")); //NON-NLS
|
||||
private static final HashSet<String> defaultDisabledKeywordListNames = new HashSet<>(Arrays.asList("Phone Numbers", "IP Addresses", "URLs", "Credit Card Numbers")); //NON-NLS
|
||||
private KeywordSearchJobSettingsPanel jobSettingsPanel = null;
|
||||
|
||||
@Override
|
||||
|
@ -1,7 +1,7 @@
|
||||
/*
|
||||
* Autopsy Forensic Browser
|
||||
*
|
||||
* Copyright 2011 Basis Technology Corp.
|
||||
* Copyright 2011-2016 Basis Technology Corp.
|
||||
* Contact: carrier <at> sleuthkit <dot> org
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
@ -18,11 +18,8 @@
|
||||
*/
|
||||
package org.sleuthkit.autopsy.keywordsearch;
|
||||
|
||||
import org.sleuthkit.datamodel.AbstractFile;
|
||||
|
||||
/**
|
||||
* Interface for a search query. Implemented by various engines or methods of
|
||||
* using the same engine. One of these is created for each query.
|
||||
* Interface for kewyord search queries.
|
||||
*/
|
||||
interface KeywordSearchQuery {
|
||||
|
||||
@ -33,7 +30,7 @@ interface KeywordSearchQuery {
|
||||
*
|
||||
* @return true if the query passed validation
|
||||
*/
|
||||
public boolean validate();
|
||||
boolean validate();
|
||||
|
||||
/**
|
||||
* execute query and return results without publishing them return results
|
||||
@ -43,7 +40,7 @@ interface KeywordSearchQuery {
|
||||
* could be a notification to stop processing
|
||||
* @return
|
||||
*/
|
||||
public QueryResults performQuery() throws NoOpenCoreException;
|
||||
QueryResults performQuery() throws NoOpenCoreException;
|
||||
|
||||
/**
|
||||
* Set an optional filter to narrow down the search Adding multiple filters
|
||||
@ -51,14 +48,14 @@ interface KeywordSearchQuery {
|
||||
*
|
||||
* @param filter filter to set on the query
|
||||
*/
|
||||
public void addFilter(KeywordQueryFilter filter);
|
||||
void addFilter(KeywordQueryFilter filter);
|
||||
|
||||
/**
|
||||
* Set an optional SOLR field to narrow down the search
|
||||
*
|
||||
* @param field field to set on the query
|
||||
*/
|
||||
public void setField(String field);
|
||||
void setField(String field);
|
||||
|
||||
/**
|
||||
* Modify the query string to be searched as a substring instead of a whole
|
||||
@ -66,39 +63,39 @@ interface KeywordSearchQuery {
|
||||
*
|
||||
* @param isSubstring
|
||||
*/
|
||||
public void setSubstringQuery();
|
||||
void setSubstringQuery();
|
||||
|
||||
/**
|
||||
* escape the query string and use the escaped string in the query
|
||||
*/
|
||||
public void escape();
|
||||
void escape();
|
||||
|
||||
/**
|
||||
*
|
||||
* @return true if query was escaped
|
||||
*/
|
||||
public boolean isEscaped();
|
||||
boolean isEscaped();
|
||||
|
||||
/**
|
||||
*
|
||||
* @return true if query is a literal query (non regex)
|
||||
*/
|
||||
public boolean isLiteral();
|
||||
boolean isLiteral();
|
||||
|
||||
/**
|
||||
* return original keyword/query string
|
||||
*
|
||||
* @return the query String supplied originally
|
||||
*/
|
||||
public String getQueryString();
|
||||
String getQueryString();
|
||||
|
||||
/**
|
||||
* return escaped keyword/query string if escaping was done
|
||||
*
|
||||
* @return the escaped query string, or original string if no escaping done
|
||||
*/
|
||||
public String getEscapedQueryString();
|
||||
String getEscapedQueryString();
|
||||
|
||||
public KeywordCachedArtifact writeSingleFileHitsToBlackBoard(String termHit, KeywordHit hit, String snippet, String listName);
|
||||
KeywordCachedArtifact writeSingleFileHitsToBlackBoard(String termHit, KeywordHit hit, String snippet, String listName);
|
||||
|
||||
}
|
||||
|
@ -29,6 +29,7 @@ import org.openide.nodes.Children;
|
||||
import org.openide.nodes.Node;
|
||||
import org.openide.util.NbBundle;
|
||||
import org.sleuthkit.autopsy.corecomponents.DataResultTopComponent;
|
||||
import org.sleuthkit.autopsy.corecomponents.TableFilterNode;
|
||||
import org.sleuthkit.autopsy.coreutils.Logger;
|
||||
|
||||
/**
|
||||
@ -55,20 +56,20 @@ class KeywordSearchQueryDelegator {
|
||||
for (KeywordList keywordList : keywordLists) {
|
||||
for (Keyword keyword : keywordList.getKeywords()) {
|
||||
KeywordSearchQuery query;
|
||||
if (keyword.isLiteral()) {
|
||||
if (keyword.searchTermIsLiteral()) {
|
||||
// literal, exact match
|
||||
if (keyword.isWholeword()) {
|
||||
if (keyword.searchTermIsWholeWord()) {
|
||||
query = new LuceneQuery(keywordList, keyword);
|
||||
query.escape();
|
||||
} // literal, substring match
|
||||
else {
|
||||
query = new TermComponentQuery(keywordList, keyword);
|
||||
query = new TermsComponentQuery(keywordList, keyword);
|
||||
query.escape();
|
||||
query.setSubstringQuery();
|
||||
}
|
||||
} // regexp
|
||||
else {
|
||||
query = new TermComponentQuery(keywordList, keyword);
|
||||
query = new TermsComponentQuery(keywordList, keyword);
|
||||
}
|
||||
queryDelegates.add(query);
|
||||
}
|
||||
@ -108,7 +109,8 @@ class KeywordSearchQueryDelegator {
|
||||
|
||||
final String pathText = NbBundle.getMessage(this.getClass(), "KeywordSearchQueryManager.pathText.text");
|
||||
|
||||
DataResultTopComponent.initInstance(pathText, rootNode, queryRequests.size(), searchResultWin);
|
||||
DataResultTopComponent.initInstance(pathText, new TableFilterNode(rootNode, true, KeywordSearch.class.getName()),
|
||||
queryRequests.size(), searchResultWin);
|
||||
|
||||
searchResultWin.requestActive();
|
||||
}
|
||||
|
@ -255,8 +255,8 @@ class KeywordSearchResultFactory extends ChildFactory<KeyValueQueryContent> {
|
||||
//the query is executed later on demand
|
||||
if (queryResults.getKeywords().size() == 1) {
|
||||
//simple case, no need to process subqueries and do special escaping
|
||||
Keyword term = queryResults.getKeywords().iterator().next();
|
||||
return constructEscapedSolrQuery(term.getQuery(), literal_query);
|
||||
Keyword keyword = queryResults.getKeywords().iterator().next();
|
||||
return constructEscapedSolrQuery(keyword.getSearchTerm(), literal_query);
|
||||
} else {
|
||||
//find terms for this content hit
|
||||
List<Keyword> hitTerms = new ArrayList<>();
|
||||
@ -274,7 +274,7 @@ class KeywordSearchResultFactory extends ChildFactory<KeyValueQueryContent> {
|
||||
int curTerm = 0;
|
||||
for (Keyword term : hitTerms) {
|
||||
//escape subqueries, MAKE SURE they are not escaped again later
|
||||
highlightQuery.append(constructEscapedSolrQuery(term.getQuery(), literal_query));
|
||||
highlightQuery.append(constructEscapedSolrQuery(term.getSearchTerm(), literal_query));
|
||||
if (lastTerm != curTerm) {
|
||||
highlightQuery.append(" "); //acts as OR ||
|
||||
}
|
||||
|
@ -55,7 +55,7 @@ class LuceneQuery implements KeywordSearchQuery {
|
||||
private final String keywordString; //original unescaped query
|
||||
private String keywordStringEscaped;
|
||||
private boolean isEscaped;
|
||||
private Keyword keywordQuery = null;
|
||||
private Keyword keyword = null;
|
||||
private KeywordList keywordList = null;
|
||||
private final List<KeywordQueryFilter> filters = new ArrayList<>();
|
||||
private String field = null;
|
||||
@ -72,15 +72,15 @@ class LuceneQuery implements KeywordSearchQuery {
|
||||
/**
|
||||
* Constructor with query to process.
|
||||
*
|
||||
* @param keywordQuery
|
||||
* @param keyword
|
||||
*/
|
||||
public LuceneQuery(KeywordList keywordList, Keyword keywordQuery) {
|
||||
public LuceneQuery(KeywordList keywordList, Keyword keyword) {
|
||||
this.keywordList = keywordList;
|
||||
this.keywordQuery = keywordQuery;
|
||||
this.keyword = keyword;
|
||||
|
||||
// @@@ BC: Long-term, we should try to get rid of this string and use only the
|
||||
// keyword object. Refactoring did not make its way through this yet.
|
||||
this.keywordString = keywordQuery.getQuery();
|
||||
this.keywordString = keyword.getSearchTerm();
|
||||
this.keywordStringEscaped = this.keywordString;
|
||||
}
|
||||
|
||||
@ -168,8 +168,8 @@ class LuceneQuery implements KeywordSearchQuery {
|
||||
//bogus - workaround the dir tree table issue
|
||||
//attributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_KEYWORD_REGEXP.getTypeID(), MODULE_NAME, "", ""));
|
||||
//selector
|
||||
if (keywordQuery != null) {
|
||||
BlackboardAttribute.ATTRIBUTE_TYPE selType = keywordQuery.getType();
|
||||
if (keyword != null) {
|
||||
BlackboardAttribute.ATTRIBUTE_TYPE selType = keyword.getArtifactAttributeType();
|
||||
if (selType != null) {
|
||||
attributes.add(new BlackboardAttribute(selType, MODULE_NAME, termHit));
|
||||
}
|
||||
|
@ -115,7 +115,7 @@ class QueryResults {
|
||||
|
||||
for (final Keyword keyword : getKeywords()) {
|
||||
if (worker.isCancelled()) {
|
||||
logger.log(Level.INFO, "Cancel detected, bailing before new keyword processed: {0}", keyword.getQuery()); //NON-NLS
|
||||
logger.log(Level.INFO, "Cancel detected, bailing before new keyword processed: {0}", keyword.getSearchTerm()); //NON-NLS
|
||||
break;
|
||||
}
|
||||
|
||||
@ -124,7 +124,7 @@ class QueryResults {
|
||||
progress.progress(keyword.toString(), unitProgress);
|
||||
}
|
||||
if (subProgress != null) {
|
||||
String hitDisplayStr = keyword.getQuery();
|
||||
String hitDisplayStr = keyword.getSearchTerm();
|
||||
if (hitDisplayStr.length() > 50) {
|
||||
hitDisplayStr = hitDisplayStr.substring(0, 49) + "...";
|
||||
}
|
||||
@ -132,7 +132,7 @@ class QueryResults {
|
||||
}
|
||||
|
||||
for (KeywordHit hit : getOneHitPerObject(keyword)) {
|
||||
String termString = keyword.getQuery();
|
||||
String termString = keyword.getSearchTerm();
|
||||
final String snippetQuery = KeywordSearchUtil.escapeLuceneQuery(termString);
|
||||
String snippet;
|
||||
try {
|
||||
@ -250,11 +250,12 @@ class QueryResults {
|
||||
|
||||
//list
|
||||
attr = written.getAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_SET_NAME.getTypeID());
|
||||
detailsSb.append("<tr>"); //NON-NLS
|
||||
detailsSb.append(NbBundle.getMessage(this.getClass(), "KeywordSearchIngestModule.listThLbl"));
|
||||
detailsSb.append("<td>").append(attr.getValueString()).append("</td>"); //NON-NLS
|
||||
detailsSb.append("</tr>"); //NON-NLS
|
||||
|
||||
if (attr != null) {
|
||||
detailsSb.append("<tr>"); //NON-NLS
|
||||
detailsSb.append(NbBundle.getMessage(this.getClass(), "KeywordSearchIngestModule.listThLbl"));
|
||||
detailsSb.append("<td>").append(attr.getValueString()).append("</td>"); //NON-NLS
|
||||
detailsSb.append("</tr>"); //NON-NLS
|
||||
}
|
||||
//regex
|
||||
if (!keywordSearchQuery.isLiteral()) {
|
||||
attr = written.getAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_KEYWORD_REGEXP.getTypeID());
|
||||
|
@ -403,7 +403,7 @@ public final class SearchRunner {
|
||||
ProgressContributor[] subProgresses = new ProgressContributor[keywords.size()];
|
||||
int i = 0;
|
||||
for (Keyword keywordQuery : keywords) {
|
||||
subProgresses[i] = AggregateProgressFactory.createProgressContributor(keywordQuery.getQuery());
|
||||
subProgresses[i] = AggregateProgressFactory.createProgressContributor(keywordQuery.getSearchTerm());
|
||||
progressGroup.addContributor(subProgresses[i]);
|
||||
i++;
|
||||
}
|
||||
@ -419,11 +419,11 @@ public final class SearchRunner {
|
||||
|
||||
for (Keyword keywordQuery : keywords) {
|
||||
if (this.isCancelled()) {
|
||||
logger.log(Level.INFO, "Cancel detected, bailing before new keyword processed: {0}", keywordQuery.getQuery()); //NON-NLS
|
||||
logger.log(Level.INFO, "Cancel detected, bailing before new keyword processed: {0}", keywordQuery.getSearchTerm()); //NON-NLS
|
||||
return null;
|
||||
}
|
||||
|
||||
final String queryStr = keywordQuery.getQuery();
|
||||
final String queryStr = keywordQuery.getSearchTerm();
|
||||
final KeywordList list = keywordToList.get(queryStr);
|
||||
|
||||
//new subProgress will be active after the initial query
|
||||
@ -434,9 +434,9 @@ public final class SearchRunner {
|
||||
|
||||
KeywordSearchQuery keywordSearchQuery = null;
|
||||
|
||||
boolean isRegex = !keywordQuery.isLiteral();
|
||||
boolean isRegex = !keywordQuery.searchTermIsLiteral();
|
||||
if (isRegex) {
|
||||
keywordSearchQuery = new TermComponentQuery(list, keywordQuery);
|
||||
keywordSearchQuery = new TermsComponentQuery(list, keywordQuery);
|
||||
} else {
|
||||
keywordSearchQuery = new LuceneQuery(list, keywordQuery);
|
||||
keywordSearchQuery.escape();
|
||||
@ -454,16 +454,16 @@ public final class SearchRunner {
|
||||
try {
|
||||
queryResults = keywordSearchQuery.performQuery();
|
||||
} catch (NoOpenCoreException ex) {
|
||||
logger.log(Level.WARNING, "Error performing query: " + keywordQuery.getQuery(), ex); //NON-NLS
|
||||
logger.log(Level.WARNING, "Error performing query: " + keywordQuery.getSearchTerm(), ex); //NON-NLS
|
||||
//no reason to continue with next query if recovery failed
|
||||
//or wait for recovery to kick in and run again later
|
||||
//likely case has closed and threads are being interrupted
|
||||
return null;
|
||||
} catch (CancellationException e) {
|
||||
logger.log(Level.INFO, "Cancel detected, bailing during keyword query: {0}", keywordQuery.getQuery()); //NON-NLS
|
||||
logger.log(Level.INFO, "Cancel detected, bailing during keyword query: {0}", keywordQuery.getSearchTerm()); //NON-NLS
|
||||
return null;
|
||||
} catch (Exception e) {
|
||||
logger.log(Level.WARNING, "Error performing query: " + keywordQuery.getQuery(), e); //NON-NLS
|
||||
logger.log(Level.WARNING, "Error performing query: " + keywordQuery.getSearchTerm(), e); //NON-NLS
|
||||
continue;
|
||||
}
|
||||
|
||||
@ -481,7 +481,7 @@ public final class SearchRunner {
|
||||
int totalUnits = newResults.getKeywords().size();
|
||||
subProgresses[keywordsSearched].start(totalUnits);
|
||||
int unitProgress = 0;
|
||||
String queryDisplayStr = keywordQuery.getQuery();
|
||||
String queryDisplayStr = keywordQuery.getSearchTerm();
|
||||
if (queryDisplayStr.length() > 50) {
|
||||
queryDisplayStr = queryDisplayStr.substring(0, 49) + "...";
|
||||
}
|
||||
@ -547,7 +547,7 @@ public final class SearchRunner {
|
||||
keywordLists.add(list);
|
||||
for (Keyword k : list.getKeywords()) {
|
||||
keywords.add(k);
|
||||
keywordToList.put(k.getQuery(), list);
|
||||
keywordToList.put(k.getSearchTerm(), list);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,433 +0,0 @@
|
||||
/*
|
||||
* Autopsy Forensic Browser
|
||||
*
|
||||
* Copyright 2011-2016 Basis Technology Corp.
|
||||
* Contact: carrier <at> sleuthkit <dot> org
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
//
|
||||
package org.sleuthkit.autopsy.keywordsearch;
|
||||
|
||||
import com.google.common.base.CharMatcher;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.logging.Level;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
import org.apache.commons.validator.routines.checkdigit.LuhnCheckDigit;
|
||||
import org.apache.solr.client.solrj.SolrQuery;
|
||||
import org.apache.solr.client.solrj.response.TermsResponse.Term;
|
||||
import org.sleuthkit.autopsy.coreutils.Logger;
|
||||
import org.sleuthkit.autopsy.coreutils.Version;
|
||||
import org.sleuthkit.autopsy.datamodel.CreditCards;
|
||||
import org.sleuthkit.datamodel.AbstractFile;
|
||||
import org.sleuthkit.datamodel.Account;
|
||||
import org.sleuthkit.datamodel.BlackboardArtifact;
|
||||
import org.sleuthkit.datamodel.BlackboardArtifact.ARTIFACT_TYPE;
|
||||
import org.sleuthkit.datamodel.BlackboardAttribute;
|
||||
import org.sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE;
|
||||
import org.sleuthkit.datamodel.TskCoreException;
|
||||
import org.sleuthkit.datamodel.TskData;
|
||||
|
||||
/**
|
||||
* Performs a regular expression query to the SOLR/Lucene instance.
|
||||
*/
|
||||
final class TermComponentQuery implements KeywordSearchQuery {
|
||||
|
||||
private static final Logger LOGGER = Logger.getLogger(TermComponentQuery.class.getName());
|
||||
private static final boolean DEBUG = Version.Type.DEVELOPMENT.equals(Version.getBuildType());
|
||||
|
||||
private static final String MODULE_NAME = KeywordSearchModuleFactory.getModuleName();
|
||||
private static final BlackboardAttribute.Type KEYWORD_SEARCH_DOCUMENT_ID = new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_KEYWORD_SEARCH_DOCUMENT_ID);
|
||||
|
||||
//TODO: move these regex and the luhn check to a new class, something like: CreditCardNumberValidator
|
||||
/*
|
||||
* Track 2 is numeric plus six punctuation symbolls :;<=>?
|
||||
*
|
||||
* This regex matches 12-19 digit ccns embeded in a track 2 formated string.
|
||||
* This regex matches (and extracts groups) even if the entire track is not
|
||||
* present as long as the part that is conforms to the track format.
|
||||
*
|
||||
*/
|
||||
private static final Pattern TRACK2_PATTERN = Pattern.compile(
|
||||
"[:;<=>?]?" //(optional)start sentinel //NON-NLS
|
||||
+ "(?<accountNumber>[3456]([ -]?\\d){11,18})" //12-19 digits, with possible single spaces or dashes in between. first digit is 3,4,5, or 6 //NON-NLS
|
||||
+ "(?:[:;<=>?]" //separator //NON-NLS
|
||||
+ "(?:(?<expiration>\\d{4})" //4 digit expiration date YYMM //NON-NLS
|
||||
+ "(?:(?<serviceCode>\\d{3})" //3 digit service code //NON-NLS
|
||||
+ "(?:(?<discretionary>[^:;<=>?]*)" //discretionary data, not containing punctuation marks //NON-NLS
|
||||
+ "(?:[:;<=>?]" //end sentinel //NON-NLS
|
||||
+ "(?<LRC>.)" //longitudinal redundancy check //NON-NLS
|
||||
+ "?)?)?)?)?)?"); //close nested optional groups //NON-NLS
|
||||
|
||||
/*
|
||||
* Track 1 is alphanumeric.
|
||||
*
|
||||
* This regex matches 12-19 digit ccns embeded in a track 1 formated string.
|
||||
* This regex matches (and extracts groups) even if the entire track is not
|
||||
* present as long as the part that is conforms to the track format.
|
||||
*/
|
||||
private static final Pattern TRACK1_PATTERN = Pattern.compile(
|
||||
"(?:" //begin nested optinal group //NON-NLS
|
||||
+ "%?" //optional start sentinal: % //NON-NLS
|
||||
+ "B)?" //format code //NON-NLS
|
||||
+ "(?<accountNumber>[3456]([ -]?\\d){11,18})" //12-19 digits, with possible single spaces or dashes in between. first digit is 3,4,5, or 6 //NON-NLS
|
||||
+ "\\^" //separator //NON-NLS
|
||||
+ "(?<name>[^^]{2,26})" //2-26 charachter name, not containing ^ //NON-NLS
|
||||
+ "(?:\\^" //separator //NON-NLS
|
||||
+ "(?:(?:\\^|(?<expiration>\\d{4}))" //separator or 4 digit expiration YYMM //NON-NLS
|
||||
+ "(?:(?:\\^|(?<serviceCode>\\d{3}))"//separator or 3 digit service code //NON-NLS
|
||||
+ "(?:(?<discretionary>[^?]*)" // discretionary data not containing separator //NON-NLS
|
||||
+ "(?:\\?" // end sentinal: ? //NON-NLS
|
||||
+ "(?<LRC>.)" //longitudinal redundancy check //NON-NLS
|
||||
+ "?)?)?)?)?)?");//close nested optional groups //NON-NLS
|
||||
private static final Pattern CCN_PATTERN = Pattern.compile("(?<ccn>[3456]([ -]?\\d){11,18})"); //12-19 digits, with possible single spaces or dashes in between. first digit is 3,4,5, or 6 //NON-NLS
|
||||
private static final LuhnCheckDigit LUHN_CHECK = new LuhnCheckDigit();
|
||||
|
||||
//corresponds to field in Solr schema, analyzed with white-space tokenizer only
|
||||
private static final String TERMS_SEARCH_FIELD = Server.Schema.CONTENT_WS.toString();
|
||||
private static final String TERMS_HANDLER = "/terms"; //NON-NLS
|
||||
private static final int TERMS_TIMEOUT = 90 * 1000; //in ms
|
||||
private static final String CASE_INSENSITIVE = "case_insensitive"; //NON-NLS
|
||||
private static final int MAX_TERMS_RESULTS = 20000;
|
||||
|
||||
private String escapedQuery;
|
||||
private final KeywordList keywordList;
|
||||
private final Keyword keyword;
|
||||
private boolean isEscaped;
|
||||
private final List<KeywordQueryFilter> filters = new ArrayList<>();
|
||||
|
||||
TermComponentQuery(KeywordList keywordList, Keyword keyword) {
|
||||
this.keyword = keyword;
|
||||
|
||||
this.keywordList = keywordList;
|
||||
this.escapedQuery = keyword.getQuery();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addFilter(KeywordQueryFilter filter) {
|
||||
this.filters.add(filter);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param field
|
||||
*
|
||||
* @deprecated This method is unused and no-op
|
||||
*/
|
||||
@Override
|
||||
@Deprecated
|
||||
public void setField(String field) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setSubstringQuery() {
|
||||
escapedQuery = ".*" + escapedQuery + ".*";
|
||||
}
|
||||
|
||||
@Override
|
||||
public void escape() {
|
||||
escapedQuery = Pattern.quote(keyword.getQuery());
|
||||
isEscaped = true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean validate() {
|
||||
if (escapedQuery.isEmpty()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
try {
|
||||
Pattern.compile(escapedQuery);
|
||||
return true;
|
||||
} catch (IllegalArgumentException ex) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEscaped() {
|
||||
return isEscaped;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isLiteral() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getEscapedQueryString() {
|
||||
return this.escapedQuery;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getQueryString() {
|
||||
return keyword.getQuery();
|
||||
}
|
||||
|
||||
@Override
|
||||
public KeywordCachedArtifact writeSingleFileHitsToBlackBoard(String termHit, KeywordHit hit, String snippet, String listName) {
|
||||
BlackboardArtifact newArtifact;
|
||||
|
||||
Collection<BlackboardAttribute> attributes = new ArrayList<>();
|
||||
if (keyword.getType() == ATTRIBUTE_TYPE.TSK_CARD_NUMBER) {
|
||||
attributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_ACCOUNT_TYPE, MODULE_NAME, Account.Type.CREDIT_CARD.name()));
|
||||
|
||||
Map<BlackboardAttribute.Type, BlackboardAttribute> parsedTrackAttributeMap = new HashMap<>();
|
||||
|
||||
//try to match it against the track 1 regex
|
||||
Matcher matcher = TRACK1_PATTERN.matcher(hit.getSnippet());
|
||||
if (matcher.find()) {
|
||||
parseTrack1Data(parsedTrackAttributeMap, matcher);
|
||||
}
|
||||
|
||||
//then try to match it against the track 2 regex
|
||||
matcher = TRACK2_PATTERN.matcher(hit.getSnippet());
|
||||
if (matcher.find()) {
|
||||
parseTrack2Data(parsedTrackAttributeMap, matcher);
|
||||
}
|
||||
|
||||
//if we couldn't parse the CCN abort this artifact
|
||||
final BlackboardAttribute ccnAttribute = parsedTrackAttributeMap.get(new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_CARD_NUMBER));
|
||||
if (ccnAttribute == null || StringUtils.isBlank(ccnAttribute.getValueString())) {
|
||||
LOGGER.log(Level.SEVERE, "Failed to parse CCN from hit: " + hit.getSnippet());
|
||||
return null;
|
||||
}
|
||||
|
||||
attributes.addAll(parsedTrackAttributeMap.values());
|
||||
|
||||
//look up the bank name, schem, etc from the BIN
|
||||
final int bin = Integer.parseInt(ccnAttribute.getValueString().substring(0, 8));
|
||||
CreditCards.BankIdentificationNumber binInfo = CreditCards.getBINInfo(bin);
|
||||
if (binInfo != null) {
|
||||
binInfo.getScheme().ifPresent(scheme
|
||||
-> attributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_CARD_SCHEME, MODULE_NAME, scheme)));
|
||||
binInfo.getCardType().ifPresent(cardType
|
||||
-> attributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_CARD_TYPE, MODULE_NAME, cardType)));
|
||||
binInfo.getBrand().ifPresent(brand
|
||||
-> attributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_BRAND_NAME, MODULE_NAME, brand)));
|
||||
binInfo.getBankName().ifPresent(bankName
|
||||
-> attributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_BANK_NAME, MODULE_NAME, bankName)));
|
||||
binInfo.getBankPhoneNumber().ifPresent(phoneNumber
|
||||
-> attributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_PHONE_NUMBER, MODULE_NAME, phoneNumber)));
|
||||
binInfo.getBankURL().ifPresent(url
|
||||
-> attributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_URL, MODULE_NAME, url)));
|
||||
binInfo.getCountry().ifPresent(country
|
||||
-> attributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_COUNTRY, MODULE_NAME, country)));
|
||||
binInfo.getBankCity().ifPresent(city
|
||||
-> attributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_CITY, MODULE_NAME, city)));
|
||||
}
|
||||
|
||||
/* if the hit is from unused or unalocated blocks, record the
|
||||
* KEYWORD_SEARCH_DOCUMENT_ID, so we can show just that chunk in the
|
||||
* UI
|
||||
*/
|
||||
if (hit.getContent() instanceof AbstractFile) {
|
||||
AbstractFile file = (AbstractFile) hit.getContent();
|
||||
if (file.getType() == TskData.TSK_DB_FILES_TYPE_ENUM.UNUSED_BLOCKS
|
||||
|| file.getType() == TskData.TSK_DB_FILES_TYPE_ENUM.UNALLOC_BLOCKS) {
|
||||
attributes.add(new BlackboardAttribute(KEYWORD_SEARCH_DOCUMENT_ID, MODULE_NAME, hit.getSolrDocumentId()));
|
||||
}
|
||||
}
|
||||
|
||||
// make account artifact
|
||||
try {
|
||||
newArtifact = hit.getContent().newArtifact(ARTIFACT_TYPE.TSK_ACCOUNT);
|
||||
} catch (TskCoreException tskCoreException) {
|
||||
LOGGER.log(Level.SEVERE, "Error adding bb artifact for account", tskCoreException); //NON-NLS
|
||||
return null;
|
||||
}
|
||||
} else {
|
||||
|
||||
//regex match
|
||||
attributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_KEYWORD, MODULE_NAME, termHit));
|
||||
//regex keyword
|
||||
attributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_KEYWORD_REGEXP, MODULE_NAME, keyword.getQuery()));
|
||||
|
||||
if (StringUtils.isNotEmpty(listName)) {
|
||||
attributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_SET_NAME, MODULE_NAME, listName));
|
||||
}
|
||||
|
||||
//make keyword hit artifact
|
||||
try {
|
||||
newArtifact = hit.getContent().newArtifact(ARTIFACT_TYPE.TSK_KEYWORD_HIT);
|
||||
|
||||
} catch (TskCoreException tskCoreException) {
|
||||
LOGGER.log(Level.SEVERE, "Error adding bb artifact for keyword hit", tskCoreException); //NON-NLS
|
||||
return null;
|
||||
}
|
||||
}
|
||||
//preview
|
||||
if (snippet != null) {
|
||||
attributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_KEYWORD_PREVIEW, MODULE_NAME, snippet));
|
||||
}
|
||||
|
||||
if (hit.isArtifactHit()) {
|
||||
attributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_ASSOCIATED_ARTIFACT, MODULE_NAME, hit.getArtifact().getArtifactID()));
|
||||
}
|
||||
|
||||
try {
|
||||
//TODO: do we still/really need this KeywordCachedArtifact class?
|
||||
newArtifact.addAttributes(attributes);
|
||||
KeywordCachedArtifact writeResult = new KeywordCachedArtifact(newArtifact);
|
||||
writeResult.add(attributes);
|
||||
return writeResult;
|
||||
} catch (TskCoreException e) {
|
||||
LOGGER.log(Level.SEVERE, "Error adding bb attributes for terms search artifact", e); //NON-NLS
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public QueryResults performQuery() throws NoOpenCoreException {
|
||||
/*
|
||||
* Execute the regex query to get a list of terms that match the regex.
|
||||
* Note that the field that is being searched is tokenized based on
|
||||
* whitespace.
|
||||
*/
|
||||
//create the query
|
||||
final SolrQuery q = new SolrQuery();
|
||||
q.setRequestHandler(TERMS_HANDLER);
|
||||
q.setTerms(true);
|
||||
q.setTermsRegexFlag(CASE_INSENSITIVE);
|
||||
q.setTermsRegex(escapedQuery);
|
||||
q.addTermsField(TERMS_SEARCH_FIELD);
|
||||
q.setTimeAllowed(TERMS_TIMEOUT);
|
||||
q.setShowDebugInfo(DEBUG);
|
||||
q.setTermsLimit(MAX_TERMS_RESULTS);
|
||||
LOGGER.log(Level.INFO, "Query: {0}", q.toString()); //NON-NLS
|
||||
|
||||
//execute the query
|
||||
List<Term> terms = null;
|
||||
try {
|
||||
terms = KeywordSearch.getServer().queryTerms(q).getTerms(TERMS_SEARCH_FIELD);
|
||||
} catch (KeywordSearchModuleException ex) {
|
||||
LOGGER.log(Level.SEVERE, "Error executing the regex terms query: " + keyword.getQuery(), ex); //NON-NLS
|
||||
//TODO: this is almost certainly wrong and guaranteed to throw a NPE at some point!!!!
|
||||
}
|
||||
|
||||
/*
|
||||
* For each term that matched the regex, query for full set of document
|
||||
* hits for that term.
|
||||
*/
|
||||
QueryResults results = new QueryResults(this, keywordList);
|
||||
int resultSize = 0;
|
||||
|
||||
for (Term term : terms) {
|
||||
final String termStr = KeywordSearchUtil.escapeLuceneQuery(term.getTerm());
|
||||
|
||||
if (keyword.getType() == ATTRIBUTE_TYPE.TSK_CARD_NUMBER) {
|
||||
//If the keyword is a credit card number, pass it through luhn validator
|
||||
Matcher matcher = CCN_PATTERN.matcher(term.getTerm());
|
||||
matcher.find();
|
||||
final String ccn = CharMatcher.anyOf(" -").removeFrom(matcher.group("ccn"));
|
||||
if (false == LUHN_CHECK.isValid(ccn)) {
|
||||
continue; //if the hit does not pass the luhn check, skip it.
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Note: we can't set filter query on terms query but setting filter
|
||||
* query on fileResults query will yield the same result
|
||||
*/
|
||||
LuceneQuery filesQuery = new LuceneQuery(keywordList, new Keyword(termStr, true));
|
||||
filters.forEach(filesQuery::addFilter);
|
||||
|
||||
try {
|
||||
QueryResults fileQueryResults = filesQuery.performQuery();
|
||||
Set<KeywordHit> filesResults = new HashSet<>();
|
||||
for (Keyword key : fileQueryResults.getKeywords()) { //flatten results into a single list
|
||||
List<KeywordHit> keyRes = fileQueryResults.getResults(key);
|
||||
resultSize += keyRes.size();
|
||||
filesResults.addAll(keyRes);
|
||||
}
|
||||
results.addResult(new Keyword(term.getTerm(), false), new ArrayList<>(filesResults));
|
||||
} catch (NoOpenCoreException | RuntimeException e) {
|
||||
LOGGER.log(Level.WARNING, "Error executing Solr query,", e); //NON-NLS
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
|
||||
//TODO limit how many results we store, not to hit memory limits
|
||||
LOGGER.log(Level.INFO, "Regex # results: {0}", resultSize); //NON-NLS
|
||||
|
||||
return results;
|
||||
}
|
||||
|
||||
@Override
|
||||
public KeywordList getKeywordList() {
|
||||
return keywordList;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add an attribute of the the given type to the given artifact with the
|
||||
* value taken from the matcher. If an attribute of the given type already
|
||||
* exists on the artifact or if the value is null, no attribute is added.
|
||||
*
|
||||
* @param attributeMap
|
||||
* @param attrType
|
||||
* @param groupName
|
||||
* @param matcher *
|
||||
*/
|
||||
static private void addAttributeIfNotAlreadyCaptured(Map<BlackboardAttribute.Type, BlackboardAttribute> attributeMap, ATTRIBUTE_TYPE attrType, String groupName, Matcher matcher) {
|
||||
BlackboardAttribute.Type type = new BlackboardAttribute.Type(attrType);
|
||||
|
||||
attributeMap.computeIfAbsent(type, (BlackboardAttribute.Type t) -> {
|
||||
String value = matcher.group(groupName);
|
||||
if (attrType.equals(ATTRIBUTE_TYPE.TSK_CARD_NUMBER)) {
|
||||
value = CharMatcher.anyOf(" -").removeFrom(value);
|
||||
}
|
||||
if (StringUtils.isNotBlank(value)) {
|
||||
return new BlackboardAttribute(attrType, MODULE_NAME, value);
|
||||
}
|
||||
return null;
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse the track 2 data from a KeywordHit and add it to the given
|
||||
* artifact.
|
||||
*
|
||||
* @param attributeMAp
|
||||
* @param matcher
|
||||
*/
|
||||
static private void parseTrack2Data(Map<BlackboardAttribute.Type, BlackboardAttribute> attributeMAp, Matcher matcher) {
|
||||
//try to add all the attrributes common to track 1 and 2
|
||||
addAttributeIfNotAlreadyCaptured(attributeMAp, ATTRIBUTE_TYPE.TSK_CARD_NUMBER, "accountNumber", matcher);
|
||||
addAttributeIfNotAlreadyCaptured(attributeMAp, ATTRIBUTE_TYPE.TSK_CARD_EXPIRATION, "expiration", matcher);
|
||||
addAttributeIfNotAlreadyCaptured(attributeMAp, ATTRIBUTE_TYPE.TSK_CARD_SERVICE_CODE, "serviceCode", matcher);
|
||||
addAttributeIfNotAlreadyCaptured(attributeMAp, ATTRIBUTE_TYPE.TSK_CARD_DISCRETIONARY, "discretionary", matcher);
|
||||
addAttributeIfNotAlreadyCaptured(attributeMAp, ATTRIBUTE_TYPE.TSK_CARD_LRC, "LRC", matcher);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse the track 1 data from a KeywordHit and add it to the given
|
||||
* artifact.
|
||||
*
|
||||
* @param attributeMap
|
||||
* @param matcher
|
||||
*/
|
||||
static private void parseTrack1Data(Map<BlackboardAttribute.Type, BlackboardAttribute> attributeMap, Matcher matcher) {
|
||||
// track 1 has all the fields present in track 2
|
||||
parseTrack2Data(attributeMap, matcher);
|
||||
//plus it also has the account holders name
|
||||
addAttributeIfNotAlreadyCaptured(attributeMap, ATTRIBUTE_TYPE.TSK_NAME_PERSON, "name", matcher);
|
||||
}
|
||||
}
|
@ -0,0 +1,517 @@
|
||||
/*
|
||||
* Autopsy Forensic Browser
|
||||
*
|
||||
* Copyright 2011-2016 Basis Technology Corp.
|
||||
* Contact: carrier <at> sleuthkit <dot> org
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.sleuthkit.autopsy.keywordsearch;
|
||||
|
||||
import com.google.common.base.CharMatcher;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.logging.Level;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
import org.apache.commons.validator.routines.checkdigit.LuhnCheckDigit;
|
||||
import org.apache.solr.client.solrj.SolrQuery;
|
||||
import org.apache.solr.client.solrj.response.TermsResponse.Term;
|
||||
import org.sleuthkit.autopsy.coreutils.Logger;
|
||||
import org.sleuthkit.autopsy.coreutils.Version;
|
||||
import org.sleuthkit.autopsy.datamodel.CreditCards;
|
||||
import org.sleuthkit.datamodel.AbstractFile;
|
||||
import org.sleuthkit.datamodel.Account;
|
||||
import org.sleuthkit.datamodel.BlackboardArtifact;
|
||||
import org.sleuthkit.datamodel.BlackboardArtifact.ARTIFACT_TYPE;
|
||||
import org.sleuthkit.datamodel.BlackboardAttribute;
|
||||
import org.sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE;
|
||||
import org.sleuthkit.datamodel.TskCoreException;
|
||||
import org.sleuthkit.datamodel.TskData;
|
||||
|
||||
/**
|
||||
* Implements a regex query that will be performed as a two step operation. In
|
||||
* the first step, the Solr terms component is used to find any terms in the
|
||||
* index that match the regex. In the second step, term queries are executed for
|
||||
* each matched term to produce the set of keyword hits for the regex.
|
||||
*/
|
||||
final class TermsComponentQuery implements KeywordSearchQuery {
|
||||
|
||||
private static final Logger LOGGER = Logger.getLogger(TermsComponentQuery.class.getName());
|
||||
private static final String MODULE_NAME = KeywordSearchModuleFactory.getModuleName();
|
||||
private static final String SEARCH_HANDLER = "/terms"; //NON-NLS
|
||||
private static final String SEARCH_FIELD = Server.Schema.CONTENT_WS.toString();
|
||||
private static final int TERMS_SEARCH_TIMEOUT = 90 * 1000; // Milliseconds
|
||||
private static final String CASE_INSENSITIVE = "case_insensitive"; //NON-NLS
|
||||
private static final boolean DEBUG_FLAG = Version.Type.DEVELOPMENT.equals(Version.getBuildType());
|
||||
private static final int MAX_TERMS_QUERY_RESULTS = 20000;
|
||||
private final KeywordList keywordList;
|
||||
private final Keyword keyword;
|
||||
private String searchTerm;
|
||||
private boolean searchTermIsEscaped;
|
||||
private final List<KeywordQueryFilter> filters = new ArrayList<>(); // THIS APPEARS TO BE UNUSED
|
||||
|
||||
/*
|
||||
* The following fields are part of the initial implementation of credit
|
||||
* card account search and should be factored into another class when time
|
||||
* permits.
|
||||
*/
|
||||
private static final Pattern CREDIT_CARD_NUM_PATTERN = Pattern.compile("(?<ccn>[3456]([ -]?\\d){11,18})"); //12-19 digits, with possible single spaces or dashes in between. First digit is 3,4,5, or 6 //NON-NLS
|
||||
private static final LuhnCheckDigit CREDIT_CARD_NUM_LUHN_CHECK = new LuhnCheckDigit();
|
||||
private static final Pattern CREDIT_CARD_TRACK1_PATTERN = Pattern.compile(
|
||||
/*
|
||||
* Track 1 is alphanumeric.
|
||||
*
|
||||
* This regex matches 12-19 digit ccns embeded in a track 1 formated
|
||||
* string. This regex matches (and extracts groups) even if the
|
||||
* entire track is not present as long as the part that is conforms
|
||||
* to the track format.
|
||||
*/
|
||||
"(?:" //begin nested optinal group //NON-NLS
|
||||
+ "%?" //optional start sentinal: % //NON-NLS
|
||||
+ "B)?" //format code //NON-NLS
|
||||
+ "(?<accountNumber>[3456]([ -]?\\d){11,18})" //12-19 digits, with possible single spaces or dashes in between. first digit is 3,4,5, or 6 //NON-NLS
|
||||
+ "\\^" //separator //NON-NLS
|
||||
+ "(?<name>[^^]{2,26})" //2-26 charachter name, not containing ^ //NON-NLS
|
||||
+ "(?:\\^" //separator //NON-NLS
|
||||
+ "(?:(?:\\^|(?<expiration>\\d{4}))" //separator or 4 digit expiration YYMM //NON-NLS
|
||||
+ "(?:(?:\\^|(?<serviceCode>\\d{3}))"//separator or 3 digit service code //NON-NLS
|
||||
+ "(?:(?<discretionary>[^?]*)" // discretionary data not containing separator //NON-NLS
|
||||
+ "(?:\\?" // end sentinal: ? //NON-NLS
|
||||
+ "(?<LRC>.)" //longitudinal redundancy check //NON-NLS
|
||||
+ "?)?)?)?)?)?");//close nested optional groups //NON-NLS
|
||||
private static final Pattern CREDIT_CARD_TRACK2_PATTERN = Pattern.compile(
|
||||
/*
|
||||
* Track 2 is numeric plus six punctuation symbolls :;<=>?
|
||||
*
|
||||
* This regex matches 12-19 digit ccns embeded in a track 2 formated
|
||||
* string. This regex matches (and extracts groups) even if the
|
||||
* entire track is not present as long as the part that is conforms
|
||||
* to the track format.
|
||||
*
|
||||
*/
|
||||
"[:;<=>?]?" //(optional)start sentinel //NON-NLS
|
||||
+ "(?<accountNumber>[3456]([ -]?\\d){11,18})" //12-19 digits, with possible single spaces or dashes in between. first digit is 3,4,5, or 6 //NON-NLS
|
||||
+ "(?:[:;<=>?]" //separator //NON-NLS
|
||||
+ "(?:(?<expiration>\\d{4})" //4 digit expiration date YYMM //NON-NLS
|
||||
+ "(?:(?<serviceCode>\\d{3})" //3 digit service code //NON-NLS
|
||||
+ "(?:(?<discretionary>[^:;<=>?]*)" //discretionary data, not containing punctuation marks //NON-NLS
|
||||
+ "(?:[:;<=>?]" //end sentinel //NON-NLS
|
||||
+ "(?<LRC>.)" //longitudinal redundancy check //NON-NLS
|
||||
+ "?)?)?)?)?)?"); //close nested optional groups //NON-NLS
|
||||
private static final BlackboardAttribute.Type KEYWORD_SEARCH_DOCUMENT_ID = new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_KEYWORD_SEARCH_DOCUMENT_ID);
|
||||
|
||||
/**
|
||||
* Constructs an object that implements a regex query that will be performed
|
||||
* as a two step operation. In the first step, the Solr terms component is
|
||||
* used to find any terms in the index that match the regex. In the second
|
||||
* step, term queries are executed for each matched term to produce the set
|
||||
* of keyword hits for the regex.
|
||||
*
|
||||
* @param keywordList A keyword list that contains the keyword that provides
|
||||
* the regex search term for the query.
|
||||
* @param keyword The keyword that provides the regex search term for
|
||||
* the query.
|
||||
*/
|
||||
// TODO: Why is both the list and the keyword added to the state of this
|
||||
// object?
|
||||
// TODO: Why is the search term not escaped and given substring wildcards,
|
||||
// if needed, here in the constructor?
|
||||
TermsComponentQuery(KeywordList keywordList, Keyword keyword) {
|
||||
this.keywordList = keywordList;
|
||||
this.keyword = keyword;
|
||||
this.searchTerm = keyword.getSearchTerm();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the keyword list that contains the keyword that provides the regex
|
||||
* search term for the query.
|
||||
*
|
||||
* @return The keyword list.
|
||||
*/
|
||||
@Override
|
||||
public KeywordList getKeywordList() {
|
||||
return keywordList;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the original search term for the query, without any escaping or, if
|
||||
* it is a literal term, the addition of wildcards for a substring search.
|
||||
*
|
||||
* @return The original search term.
|
||||
*/
|
||||
@Override
|
||||
public String getQueryString() {
|
||||
return keyword.getSearchTerm();
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicates whether or not the search term for the query is a literal term
|
||||
* that needs have wildcards added to it to make the query a substring
|
||||
* search.
|
||||
*
|
||||
* @return True or false.
|
||||
*/
|
||||
@Override
|
||||
public boolean isLiteral() {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds wild cards to the search term for the query, which makes the query a
|
||||
* substring search, if it is a literal search term.
|
||||
*/
|
||||
@Override
|
||||
public void setSubstringQuery() {
|
||||
searchTerm = ".*" + searchTerm + ".*";
|
||||
}
|
||||
|
||||
/**
|
||||
* Escapes the search term for the query.
|
||||
*/
|
||||
@Override
|
||||
public void escape() {
|
||||
searchTerm = Pattern.quote(keyword.getSearchTerm());
|
||||
searchTermIsEscaped = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicates whether or not the search term has been escaped yet.
|
||||
*
|
||||
* @return True or false.
|
||||
*/
|
||||
@Override
|
||||
public boolean isEscaped() {
|
||||
return searchTermIsEscaped;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the escaped search term for the query, assuming it has been escaped
|
||||
* by a call to TermsComponentQuery.escape.
|
||||
*
|
||||
* @return The search term, possibly escaped.
|
||||
*/
|
||||
@Override
|
||||
public String getEscapedQueryString() {
|
||||
return this.searchTerm;
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicates whether or not the search term is a valid regex.
|
||||
*
|
||||
* @return True or false.
|
||||
*/
|
||||
@Override
|
||||
public boolean validate() {
|
||||
if (searchTerm.isEmpty()) {
|
||||
return false;
|
||||
}
|
||||
try {
|
||||
Pattern.compile(searchTerm);
|
||||
return true;
|
||||
} catch (IllegalArgumentException ex) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Does nothing, not applicable to a regex query, which always searches a
|
||||
* field created specifically for regex sesarches.
|
||||
*
|
||||
* @param field The name of a Solr document field to search.
|
||||
*/
|
||||
@Override
|
||||
public void setField(String field) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a filter to the query.
|
||||
*
|
||||
* @param filter The filter.
|
||||
*/
|
||||
// TODO: Document this better.
|
||||
@Override
|
||||
public void addFilter(KeywordQueryFilter filter) {
|
||||
this.filters.add(filter);
|
||||
}
|
||||
|
||||
/**
|
||||
* Executes the regex query as a two step operation. In the first step, the
|
||||
* Solr terms component is used to find any terms in the index that match
|
||||
* the regex. In the second step, term queries are executed for each matched
|
||||
* term to produce the set of keyword hits for the regex.
|
||||
*
|
||||
* @return A QueryResult object or null.
|
||||
*
|
||||
* @throws NoOpenCoreException
|
||||
*/
|
||||
// TODO: Make it so this cannot cause NPEs; this method should throw
|
||||
// exceptions instead of logging them and returning null.
|
||||
@Override
|
||||
public QueryResults performQuery() throws NoOpenCoreException {
|
||||
/*
|
||||
* Do a query using the Solr terms component to find any terms in the
|
||||
* index that match the regex.
|
||||
*/
|
||||
final SolrQuery termsQuery = new SolrQuery();
|
||||
termsQuery.setRequestHandler(SEARCH_HANDLER);
|
||||
termsQuery.setTerms(true);
|
||||
termsQuery.setTermsRegexFlag(CASE_INSENSITIVE);
|
||||
termsQuery.setTermsRegex(searchTerm);
|
||||
termsQuery.addTermsField(SEARCH_FIELD);
|
||||
termsQuery.setTimeAllowed(TERMS_SEARCH_TIMEOUT);
|
||||
termsQuery.setShowDebugInfo(DEBUG_FLAG);
|
||||
termsQuery.setTermsLimit(MAX_TERMS_QUERY_RESULTS);
|
||||
List<Term> terms = null;
|
||||
try {
|
||||
terms = KeywordSearch.getServer().queryTerms(termsQuery).getTerms(SEARCH_FIELD);
|
||||
} catch (KeywordSearchModuleException ex) {
|
||||
LOGGER.log(Level.SEVERE, "Error executing the regex terms query: " + keyword.getSearchTerm(), ex); //NON-NLS
|
||||
//TODO: this is almost certainly wrong and guaranteed to throw a NPE at some point!!!!
|
||||
}
|
||||
|
||||
/*
|
||||
* Do a term query for each term that matched the regex.
|
||||
*/
|
||||
QueryResults results = new QueryResults(this, keywordList);
|
||||
for (Term term : terms) {
|
||||
/*
|
||||
* If searching for credit card account numbers, do a Luhn check on
|
||||
* the term and discard it if it does not pass.
|
||||
*/
|
||||
if (keyword.getArtifactAttributeType() == ATTRIBUTE_TYPE.TSK_CARD_NUMBER) {
|
||||
Matcher matcher = CREDIT_CARD_NUM_PATTERN.matcher(term.getTerm());
|
||||
matcher.find();
|
||||
final String ccn = CharMatcher.anyOf(" -").removeFrom(matcher.group("ccn"));
|
||||
if (false == CREDIT_CARD_NUM_LUHN_CHECK.isValid(ccn)) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Do an ordinary query with the escaped term and convert the query
|
||||
* results into a single list of keyword hits without duplicates.
|
||||
*
|
||||
* Note that the filters field appears to be unused. There is an old
|
||||
* comment here, what does it mean? "Note: we can't set filter query
|
||||
* on terms query but setting filter query on fileResults query will
|
||||
* yield the same result." The filter is NOT being added to the term
|
||||
* query.
|
||||
*/
|
||||
String escapedTerm = KeywordSearchUtil.escapeLuceneQuery(term.getTerm());
|
||||
LuceneQuery termQuery = new LuceneQuery(keywordList, new Keyword(escapedTerm, true));
|
||||
filters.forEach(termQuery::addFilter); // This appears to be unused
|
||||
QueryResults termQueryResult = termQuery.performQuery();
|
||||
Set<KeywordHit> termHits = new HashSet<>();
|
||||
for (Keyword word : termQueryResult.getKeywords()) {
|
||||
termHits.addAll(termQueryResult.getResults(word));
|
||||
}
|
||||
results.addResult(new Keyword(term.getTerm(), false), new ArrayList<>(termHits));
|
||||
}
|
||||
return results;
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts the keyword hits for a given search term into artifacts.
|
||||
*
|
||||
* @param searchTerm The search term.
|
||||
* @param hit The keyword hit.
|
||||
* @param snippet The document snippet that contains the hit
|
||||
* @param listName The name of the keyword list that contained the keyword
|
||||
* for which the hit was found.
|
||||
*
|
||||
*
|
||||
*
|
||||
* @return An object that wraps an artifact and a mapping by id of its
|
||||
* attributes.
|
||||
*/
|
||||
// TODO: Are we actually making meaningful use of the KeywordCachedArtifact
|
||||
// class?
|
||||
@Override
|
||||
public KeywordCachedArtifact writeSingleFileHitsToBlackBoard(String searchTerm, KeywordHit hit, String snippet, String listName) {
|
||||
/*
|
||||
* Create either a "plain vanilla" keyword hit artifact with keyword and
|
||||
* regex attributes, or a credit card account artifact with attributes
|
||||
* parsed from from the snippet for the hit and looked up based on the
|
||||
* parsed bank identifcation number.
|
||||
*/
|
||||
BlackboardArtifact newArtifact;
|
||||
Collection<BlackboardAttribute> attributes = new ArrayList<>();
|
||||
if (keyword.getArtifactAttributeType() != ATTRIBUTE_TYPE.TSK_CARD_NUMBER) {
|
||||
attributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_KEYWORD, MODULE_NAME, searchTerm));
|
||||
attributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_KEYWORD_REGEXP, MODULE_NAME, keyword.getSearchTerm()));
|
||||
try {
|
||||
newArtifact = hit.getContent().newArtifact(ARTIFACT_TYPE.TSK_KEYWORD_HIT);
|
||||
|
||||
} catch (TskCoreException ex) {
|
||||
LOGGER.log(Level.SEVERE, "Error adding artifact for keyword hit to blackboard", ex); //NON-NLS
|
||||
return null;
|
||||
}
|
||||
} else {
|
||||
/*
|
||||
* Parse the credit card account attributes from the snippet for the
|
||||
* hit.
|
||||
*/
|
||||
attributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_ACCOUNT_TYPE, MODULE_NAME, Account.Type.CREDIT_CARD.name()));
|
||||
Map<BlackboardAttribute.Type, BlackboardAttribute> parsedTrackAttributeMap = new HashMap<>();
|
||||
Matcher matcher = CREDIT_CARD_TRACK1_PATTERN.matcher(hit.getSnippet());
|
||||
if (matcher.find()) {
|
||||
parseTrack1Data(parsedTrackAttributeMap, matcher);
|
||||
}
|
||||
matcher = CREDIT_CARD_TRACK2_PATTERN.matcher(hit.getSnippet());
|
||||
if (matcher.find()) {
|
||||
parseTrack2Data(parsedTrackAttributeMap, matcher);
|
||||
}
|
||||
final BlackboardAttribute ccnAttribute = parsedTrackAttributeMap.get(new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_CARD_NUMBER));
|
||||
if (ccnAttribute == null || StringUtils.isBlank(ccnAttribute.getValueString())) {
|
||||
if (hit.isArtifactHit()) {
|
||||
LOGGER.log(Level.SEVERE, String.format("Failed to parse credit card account number for artifact keyword hit: term = %s, snippet = '%s', artifact id = %d", searchTerm, hit.getSnippet(), hit.getArtifact().getArtifactID())); //NON-NLS
|
||||
} else {
|
||||
LOGGER.log(Level.SEVERE, String.format("Failed to parse credit card account number for content keyword hit: term = %s, snippet = '%s', object id = %d", searchTerm, hit.getSnippet(), hit.getContent().getId())); //NON-NLS
|
||||
}
|
||||
return null;
|
||||
}
|
||||
attributes.addAll(parsedTrackAttributeMap.values());
|
||||
|
||||
/*
|
||||
* Look up the bank name, scheme, etc. attributes for the bank
|
||||
* indentification number (BIN).
|
||||
*/
|
||||
final int bin = Integer.parseInt(ccnAttribute.getValueString().substring(0, 8));
|
||||
CreditCards.BankIdentificationNumber binInfo = CreditCards.getBINInfo(bin);
|
||||
if (binInfo != null) {
|
||||
binInfo.getScheme().ifPresent(scheme
|
||||
-> attributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_CARD_SCHEME, MODULE_NAME, scheme)));
|
||||
binInfo.getCardType().ifPresent(cardType
|
||||
-> attributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_CARD_TYPE, MODULE_NAME, cardType)));
|
||||
binInfo.getBrand().ifPresent(brand
|
||||
-> attributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_BRAND_NAME, MODULE_NAME, brand)));
|
||||
binInfo.getBankName().ifPresent(bankName
|
||||
-> attributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_BANK_NAME, MODULE_NAME, bankName)));
|
||||
binInfo.getBankPhoneNumber().ifPresent(phoneNumber
|
||||
-> attributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_PHONE_NUMBER, MODULE_NAME, phoneNumber)));
|
||||
binInfo.getBankURL().ifPresent(url
|
||||
-> attributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_URL, MODULE_NAME, url)));
|
||||
binInfo.getCountry().ifPresent(country
|
||||
-> attributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_COUNTRY, MODULE_NAME, country)));
|
||||
binInfo.getBankCity().ifPresent(city
|
||||
-> attributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_CITY, MODULE_NAME, city)));
|
||||
}
|
||||
|
||||
/*
|
||||
* If the hit is from unused or unallocated space, record the Solr
|
||||
* document id to support showing just the chunk that contained the
|
||||
* hit.
|
||||
*/
|
||||
if (hit.getContent() instanceof AbstractFile) {
|
||||
AbstractFile file = (AbstractFile) hit.getContent();
|
||||
if (file.getType() == TskData.TSK_DB_FILES_TYPE_ENUM.UNUSED_BLOCKS
|
||||
|| file.getType() == TskData.TSK_DB_FILES_TYPE_ENUM.UNALLOC_BLOCKS) {
|
||||
attributes.add(new BlackboardAttribute(KEYWORD_SEARCH_DOCUMENT_ID, MODULE_NAME, hit.getSolrDocumentId()));
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Create an account artifact.
|
||||
*/
|
||||
try {
|
||||
newArtifact = hit.getContent().newArtifact(ARTIFACT_TYPE.TSK_ACCOUNT);
|
||||
} catch (TskCoreException ex) {
|
||||
LOGGER.log(Level.SEVERE, "Error adding artifact for account to blackboard", ex); //NON-NLS
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
if (StringUtils.isNotBlank(listName)) {
|
||||
attributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_SET_NAME, MODULE_NAME, listName));
|
||||
}
|
||||
if (snippet != null) {
|
||||
attributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_KEYWORD_PREVIEW, MODULE_NAME, snippet));
|
||||
}
|
||||
if (hit.isArtifactHit()) {
|
||||
attributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_ASSOCIATED_ARTIFACT, MODULE_NAME, hit.getArtifact().getArtifactID()));
|
||||
}
|
||||
|
||||
try {
|
||||
newArtifact.addAttributes(attributes);
|
||||
KeywordCachedArtifact writeResult = new KeywordCachedArtifact(newArtifact);
|
||||
writeResult.add(attributes);
|
||||
return writeResult;
|
||||
} catch (TskCoreException e) {
|
||||
LOGGER.log(Level.SEVERE, "Error adding bb attributes for terms search artifact", e); //NON-NLS
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses the track 2 data from the snippet for a credit card account number
|
||||
* hit and turns them into artifact attributes.
|
||||
*
|
||||
* @param attributesMap A map of artifact attribute objects, used to avoid
|
||||
* creating duplicate attributes.
|
||||
* @param matcher A matcher for the snippet.
|
||||
*/
|
||||
static private void parseTrack2Data(Map<BlackboardAttribute.Type, BlackboardAttribute> attributesMap, Matcher matcher) {
|
||||
addAttributeIfNotAlreadyCaptured(attributesMap, ATTRIBUTE_TYPE.TSK_CARD_NUMBER, "accountNumber", matcher);
|
||||
addAttributeIfNotAlreadyCaptured(attributesMap, ATTRIBUTE_TYPE.TSK_CARD_EXPIRATION, "expiration", matcher);
|
||||
addAttributeIfNotAlreadyCaptured(attributesMap, ATTRIBUTE_TYPE.TSK_CARD_SERVICE_CODE, "serviceCode", matcher);
|
||||
addAttributeIfNotAlreadyCaptured(attributesMap, ATTRIBUTE_TYPE.TSK_CARD_DISCRETIONARY, "discretionary", matcher);
|
||||
addAttributeIfNotAlreadyCaptured(attributesMap, ATTRIBUTE_TYPE.TSK_CARD_LRC, "LRC", matcher);
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses the track 1 data from the snippet for a credit card account number
|
||||
* hit and turns them into artifact attributes. The track 1 data has the
|
||||
* same fields as the track two data, plus the account holder's name.
|
||||
*
|
||||
* @param attributesMap A map of artifact attribute objects, used to avoid
|
||||
* creating duplicate attributes.
|
||||
* @param matcher A matcher for the snippet.
|
||||
*/
|
||||
static private void parseTrack1Data(Map<BlackboardAttribute.Type, BlackboardAttribute> attributeMap, Matcher matcher) {
|
||||
parseTrack2Data(attributeMap, matcher);
|
||||
addAttributeIfNotAlreadyCaptured(attributeMap, ATTRIBUTE_TYPE.TSK_NAME_PERSON, "name", matcher);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates an attribute of the the given type to the given artifact with a
|
||||
* value parsed from the snippet for a credit account number hit.
|
||||
*
|
||||
* @param attributesMap A map of artifact attribute objects, used to avoid
|
||||
* creating duplicate attributes.
|
||||
* @param attrType The type of attribute to create.
|
||||
* @param groupName The group name of the regular expression that was
|
||||
* used to parse the attribute data.
|
||||
* @param matcher A matcher for the snippet.
|
||||
*/
|
||||
static private void addAttributeIfNotAlreadyCaptured(Map<BlackboardAttribute.Type, BlackboardAttribute> attributeMap, ATTRIBUTE_TYPE attrType, String groupName, Matcher matcher) {
|
||||
BlackboardAttribute.Type type = new BlackboardAttribute.Type(attrType);
|
||||
attributeMap.computeIfAbsent(type, (BlackboardAttribute.Type t) -> {
|
||||
String value = matcher.group(groupName);
|
||||
if (attrType.equals(ATTRIBUTE_TYPE.TSK_CARD_NUMBER)) {
|
||||
value = CharMatcher.anyOf(" -").removeFrom(value);
|
||||
}
|
||||
if (StringUtils.isNotBlank(value)) {
|
||||
return new BlackboardAttribute(attrType, MODULE_NAME, value);
|
||||
}
|
||||
return null;
|
||||
});
|
||||
}
|
||||
|
||||
}
|
@ -99,7 +99,7 @@ final class XmlKeywordSearchList extends KeywordSearchList {
|
||||
doc.appendChild(rootEl);
|
||||
|
||||
for (String listName : theLists.keySet()) {
|
||||
if (theLists.get(listName).isLocked() == true) {
|
||||
if (theLists.get(listName).isEditable() == true) {
|
||||
continue;
|
||||
}
|
||||
KeywordList list = theLists.get(listName);
|
||||
@ -123,13 +123,13 @@ final class XmlKeywordSearchList extends KeywordSearchList {
|
||||
|
||||
for (Keyword keyword : keywords) {
|
||||
Element keywordEl = doc.createElement(KEYWORD_EL);
|
||||
String literal = keyword.isLiteral() ? "true" : "false"; //NON-NLS
|
||||
String literal = keyword.searchTermIsLiteral() ? "true" : "false"; //NON-NLS
|
||||
keywordEl.setAttribute(KEYWORD_LITERAL_ATTR, literal);
|
||||
BlackboardAttribute.ATTRIBUTE_TYPE selectorType = keyword.getType();
|
||||
BlackboardAttribute.ATTRIBUTE_TYPE selectorType = keyword.getArtifactAttributeType();
|
||||
if (selectorType != null) {
|
||||
keywordEl.setAttribute(KEYWORD_SELECTOR_ATTR, selectorType.getLabel());
|
||||
}
|
||||
keywordEl.setTextContent(keyword.getQuery());
|
||||
keywordEl.setTextContent(keyword.getSearchTerm());
|
||||
listEl.appendChild(keywordEl);
|
||||
}
|
||||
rootEl.appendChild(listEl);
|
||||
@ -199,7 +199,7 @@ final class XmlKeywordSearchList extends KeywordSearchList {
|
||||
String selector = wordEl.getAttribute(KEYWORD_SELECTOR_ATTR);
|
||||
if (!selector.equals("")) {
|
||||
BlackboardAttribute.ATTRIBUTE_TYPE selectorType = BlackboardAttribute.ATTRIBUTE_TYPE.fromLabel(selector);
|
||||
keyword.setType(selectorType);
|
||||
keyword.setArtifactAttributeType(selectorType);
|
||||
}
|
||||
words.add(keyword);
|
||||
|
||||
|
18
NEWS.txt
18
NEWS.txt
@ -1,13 +1,15 @@
|
||||
---------------- VERSION 4.2.0 --------------
|
||||
Improvements:
|
||||
- Credit card account search
|
||||
- Encoding/decoding of extracted files to avoid anti-virus alerts/quarantine
|
||||
- Options panel for managing custom tag names
|
||||
- Options panel for setting external viewer associations
|
||||
- Keyboard shortcut for applying Bookmark tags
|
||||
- Improved PhotoRec carver ingest module cancellation responsiveness
|
||||
- Results content viewer formats dates instead of showing raw seconds since epoch
|
||||
- Update to PostgreSQL 9.5
|
||||
- Credit card account search.
|
||||
- Encoding/decoding of extracted files to avoid anti-virus alerts/quarantine.
|
||||
- Ingest history (start time, end time, status, which versions of which ingest modules were run).
|
||||
- Ingest history used to warn before doing redundant analysis.
|
||||
- Options panel for managing custom tag names.
|
||||
- Options panel for setting external viewer associations.
|
||||
- Keyboard shortcut for applying Bookmark tags.
|
||||
- Improved PhotoRec carver ingest module cancellation responsiveness.
|
||||
- Results content viewer formats dates.
|
||||
- Update to PostgreSQL 9.5.
|
||||
- Assorted bug fixes and minor enhancements.
|
||||
|
||||
---------------- VERSION 4.1.1 --------------
|
||||
|
@ -1,5 +1,5 @@
|
||||
#Updated by build script
|
||||
#Wed, 12 Oct 2016 13:08:27 -0400
|
||||
#Sat, 22 Oct 2016 14:27:47 -0400
|
||||
LBL_splash_window_title=Starting Autopsy
|
||||
SPLASH_HEIGHT=314
|
||||
SPLASH_WIDTH=538
|
||||
|
@ -1,4 +1,4 @@
|
||||
#Updated by build script
|
||||
#Wed, 12 Oct 2016 13:08:27 -0400
|
||||
#Sat, 22 Oct 2016 14:27:47 -0400
|
||||
CTL_MainWindow_Title=Autopsy 4.2.0
|
||||
CTL_MainWindow_Title_No_Project=Autopsy 4.2.0
|
||||
|
@ -43,68 +43,40 @@
|
||||
<!-- copy 64-bit dlls into the installer folder -->
|
||||
<target name="copyWinTskLibs64ToBaseDir" if="win64.TskLib.exists">
|
||||
<fileset dir="${win64.TskLib.path}" id="win64dlls">
|
||||
<include name="libewf.dll" />
|
||||
<include name="libvmdk.dll"/>
|
||||
<include name="libvhdi.dll"/>
|
||||
<include name="zlib.dll"/>
|
||||
<include name="*.dll" />
|
||||
<exclude name="libtsk_jni.dll"/>
|
||||
</fileset>
|
||||
|
||||
<fileset dir="${win64.TskLib.postgres_path}" id="postgres64dlls">
|
||||
<include name="libeay32.dll"/>
|
||||
<include name="ssleay32.dll"/>
|
||||
<include name="libintl-8.dll"/>
|
||||
<include name="libiconv-2.dll"/>
|
||||
<include name="libpq.dll"/>
|
||||
<include name="msvcr120.dll"/>
|
||||
</fileset>
|
||||
|
||||
<copy todir="${amd64}" overwrite="true">
|
||||
<fileset refid="win64dlls" />
|
||||
<fileset refid="postgres64dlls" />
|
||||
</copy>
|
||||
|
||||
<copy todir="${x86_64}" overwrite="true">
|
||||
<fileset refid="win64dlls" />
|
||||
<fileset refid="postgres64dlls" />
|
||||
</copy>
|
||||
</target>
|
||||
|
||||
<!-- copy 32-bit dlls into the installer folder -->
|
||||
<target name="copyWinTskLibs32ToBaseDir" if="win32.TskLib.exists">
|
||||
<fileset dir="${win32.TskLib.path}" id="win32dlls">
|
||||
<include name="zlib.dll" />
|
||||
<include name="libvmdk.dll"/>
|
||||
<include name="libvhdi.dll"/>
|
||||
<include name="libewf.dll"/>
|
||||
<include name="*.dll" />
|
||||
<exclude name="libtsk_jni.dll"/>
|
||||
</fileset>
|
||||
|
||||
<fileset dir="${win32.TskLib.postgres_path}" id="postgres32dlls">
|
||||
<include name="libeay32.dll"/>
|
||||
<include name="ssleay32.dll"/>
|
||||
<include name="libintl-8.dll"/>
|
||||
<include name="libiconv-2.dll"/>
|
||||
<include name="libpq.dll"/>
|
||||
<include name="msvcr120.dll"/>
|
||||
</fileset>
|
||||
|
||||
<copy todir="${i386}" overwrite="true">
|
||||
<fileset refid="win32dlls" />
|
||||
<fileset refid="postgres32dlls" />
|
||||
</copy>
|
||||
|
||||
<copy todir="${x86}" overwrite="true">
|
||||
<fileset refid="win32dlls" />
|
||||
<fileset refid="postgres32dlls" />
|
||||
</copy>
|
||||
|
||||
<copy todir="${i586}" overwrite="true">
|
||||
<fileset refid="win32dlls" />
|
||||
<fileset refid="postgres32dlls" />
|
||||
</copy>
|
||||
|
||||
<copy todir="${i686}" overwrite="true">
|
||||
<fileset refid="win32dlls" />
|
||||
<fileset refid="postgres32dlls" />
|
||||
</copy>
|
||||
</target>
|
||||
|
||||
@ -115,57 +87,4 @@
|
||||
<antcall target="copyWinTskLibs64ToBaseDir" inheritRefs="true" />
|
||||
</target>
|
||||
|
||||
<!-- CRT LIBS TO ZIP - gets called from build.xml -->
|
||||
<target name="copyLibsToZip" depends="copyCRT32ToZIP,copyCRT64ToZIP"/>
|
||||
|
||||
<target name="copyCRT32ToZIP">
|
||||
|
||||
<!-- verify we have the 32-bit dlls -->
|
||||
<property name="CRT32.path" value="${thirdparty.dir}/crt/win32"/>
|
||||
<available file="${CRT32.path}" property="crtFound"/>
|
||||
<fail unless="crtFound" message="32-bit CRT not found in the thirdparty repo in path: ${CRT32.path}"/>
|
||||
|
||||
<!-- copy them from third party -->
|
||||
<property name="zip-lib-path" value="${zip-tmp}/${app.name}/${app.name}/modules/lib/"/>
|
||||
<fileset dir="${CRT32.path}" id="crt32dlls">
|
||||
<include name="*.dll"/>
|
||||
</fileset>
|
||||
|
||||
<copy todir="${zip-lib-path}/x86" overwrite="true">
|
||||
<fileset refid="crt32dlls"/>
|
||||
</copy>
|
||||
|
||||
<copy todir="${zip-lib-path}/i386" overwrite="true">
|
||||
<fileset refid="crt32dlls"/>
|
||||
</copy>
|
||||
|
||||
<copy todir="${zip-lib-path}/i586" overwrite="true">
|
||||
<fileset refid="crt32dlls"/>
|
||||
</copy>
|
||||
|
||||
<copy todir="${zip-lib-path}/i686" overwrite="true">
|
||||
<fileset refid="crt32dlls"/>
|
||||
</copy>
|
||||
</target>
|
||||
|
||||
<target name="copyCRT64ToZIP">
|
||||
<!-- Verify we have the 64-bit -->
|
||||
<property name="CRT64.path" value="${thirdparty.dir}/crt/win64"/>
|
||||
<available file="${CRT64.path}" property="crtFound"/>
|
||||
<fail unless="crtFound" message="64-bit CRT not found in the thirdparty repo in path: ${CRT64.path}"/>
|
||||
|
||||
<!-- Copy the libs -->
|
||||
<property name="zip-lib-path" value="${zip-tmp}/${app.name}/${app.name}/modules/lib/"/>
|
||||
<fileset dir="${CRT64.path}" id="crt64dlls">
|
||||
<include name="*.dll"/>
|
||||
</fileset>
|
||||
|
||||
<copy todir="${zip-lib-path}/x86_64" overwrite="true">
|
||||
<fileset refid="crt64dlls"/>
|
||||
</copy>
|
||||
|
||||
<copy todir="${zip-lib-path}/amd64" overwrite="true">
|
||||
<fileset refid="crt64dlls"/>
|
||||
</copy>
|
||||
</target>
|
||||
</project>
|
||||
|
@ -92,8 +92,6 @@
|
||||
</then>
|
||||
</if>
|
||||
|
||||
<antcall target="copyLibsToZip"/>
|
||||
|
||||
<property name="app.property.file" value="${zip-tmp}/${app.name}/etc/${app.name}.conf" />
|
||||
<!-- for Japanese localized version add option: -Duser.language=ja -->
|
||||
<property name="jvm.options" value=""--branding ${app.name} -J-Xms24m -J-XX:MaxPermSize=128M -J-Xverify:none -J-Xdock:name=${app.title}"" />
|
||||
|
@ -38,7 +38,7 @@ PROJECT_NAME = "Autopsy User Documentation"
|
||||
# could be handy for archiving the generated documentation or if some version
|
||||
# control system is used.
|
||||
|
||||
PROJECT_NUMBER = 4.1
|
||||
PROJECT_NUMBER = 4.2
|
||||
|
||||
# Using the PROJECT_BRIEF tag one can provide an optional one line description
|
||||
# for a project that appears at the top of each page and should give viewer a
|
||||
@ -1025,7 +1025,7 @@ GENERATE_HTML = YES
|
||||
# The default directory is: html.
|
||||
# This tag requires that the tag GENERATE_HTML is set to YES.
|
||||
|
||||
HTML_OUTPUT = 4.1
|
||||
HTML_OUTPUT = 4.2
|
||||
|
||||
# The HTML_FILE_EXTENSION tag can be used to specify the file extension for each
|
||||
# generated HTML page (for example: .htm, .php, .asp).
|
||||
|
@ -1063,7 +1063,7 @@ GENERATE_HTML = YES
|
||||
# The default directory is: html.
|
||||
# This tag requires that the tag GENERATE_HTML is set to YES.
|
||||
|
||||
HTML_OUTPUT = api-docs/4.1/
|
||||
HTML_OUTPUT = api-docs/4.2/
|
||||
|
||||
# The HTML_FILE_EXTENSION tag can be used to specify the file extension for each
|
||||
# generated HTML page (for example: .htm, .php, .asp).
|
||||
|
@ -6,8 +6,8 @@ app.name=${branding.token}
|
||||
### if left unset, version will default to today's date
|
||||
app.version=4.2.0
|
||||
### build.type must be one of: DEVELOPMENT, RELEASE
|
||||
build.type=RELEASE
|
||||
#build.type=DEVELOPMENT
|
||||
#build.type=RELEASE
|
||||
build.type=DEVELOPMENT
|
||||
|
||||
project.org.sleuthkit.autopsy.imagegallery=ImageGallery
|
||||
update_versions=false
|
||||
|
9
thirdparty/crt/update.bat
vendored
9
thirdparty/crt/update.bat
vendored
@ -1,9 +0,0 @@
|
||||
REM Updates the 32-bit and 64-bit VS Runtime dlls
|
||||
REM Needs to be run from a 64-bit command prompt
|
||||
REM Otherwise Windows will put 32-bit dlls in system32
|
||||
copy c:\windows\system32\msvcr100.dll win64
|
||||
copy c:\windows\system32\msvcp100.dll win64
|
||||
copy c:\windows\system32\msvcr120.dll win64
|
||||
copy c:\windows\sysWoW64\msvcr100.dll win32
|
||||
copy c:\windows\sysWow64\msvcp100.dll win32
|
||||
copy c:\windows\sysWow64\msvcr120.dll win32
|
BIN
thirdparty/crt/win32/msvcp100.dll
vendored
BIN
thirdparty/crt/win32/msvcp100.dll
vendored
Binary file not shown.
BIN
thirdparty/crt/win32/msvcr100.dll
vendored
BIN
thirdparty/crt/win32/msvcr100.dll
vendored
Binary file not shown.
BIN
thirdparty/crt/win64/msvcp100.dll
vendored
BIN
thirdparty/crt/win64/msvcp100.dll
vendored
Binary file not shown.
BIN
thirdparty/crt/win64/msvcr100.dll
vendored
BIN
thirdparty/crt/win64/msvcr100.dll
vendored
Binary file not shown.
Loading…
x
Reference in New Issue
Block a user