mirror of
https://github.com/elisspace/autopsy.git
synced 2026-09-29 13:59:52 +00:00
package change
This commit is contained in:
@@ -1,146 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
|
||||
<Form version="1.3" maxVersion="1.9" type="org.netbeans.modules.form.forminfo.JDialogFormInfo">
|
||||
<Properties>
|
||||
<Property name="defaultCloseOperation" type="int" value="2"/>
|
||||
</Properties>
|
||||
<SyntheticProperties>
|
||||
<SyntheticProperty name="formSizePolicy" type="int" value="1"/>
|
||||
<SyntheticProperty name="generateCenter" type="boolean" value="false"/>
|
||||
</SyntheticProperties>
|
||||
<AuxValues>
|
||||
<AuxValue name="FormSettings_autoResourcing" type="java.lang.Integer" value="0"/>
|
||||
<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="false"/>
|
||||
<AuxValue name="FormSettings_i18nAutoMode" type="java.lang.Boolean" value="false"/>
|
||||
<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" attributes="0">
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<Component id="validationLabel" alignment="0" max="32767" attributes="0"/>
|
||||
<Group type="102" alignment="1" attributes="0">
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<Component id="domainSuffixLabel" alignment="0" min="-2" max="-2" attributes="0"/>
|
||||
<Component id="categoryLabel" alignment="0" min="-2" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
<EmptySpace max="32767" attributes="0"/>
|
||||
<Group type="103" groupAlignment="0" max="-2" attributes="0">
|
||||
<Component id="categoryTextField" pref="272" max="32767" attributes="0"/>
|
||||
<Component id="domainSuffixTextField" max="32767" attributes="0"/>
|
||||
</Group>
|
||||
</Group>
|
||||
<Group type="102" alignment="1" attributes="0">
|
||||
<EmptySpace min="0" pref="216" max="32767" attributes="0"/>
|
||||
<Component id="saveButton" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Component id="cancelButton" min="-2" max="-2" 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"/>
|
||||
<Group type="103" groupAlignment="1" attributes="0">
|
||||
<Group type="102" attributes="0">
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<Component id="categoryLabel" min="-2" max="-2" attributes="0"/>
|
||||
<Component id="categoryTextField" min="-2" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
<EmptySpace type="separate" max="-2" attributes="0"/>
|
||||
<Component id="domainSuffixTextField" min="-2" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
<Component id="domainSuffixLabel" min="-2" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Component id="validationLabel" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace type="unrelated" max="-2" attributes="0"/>
|
||||
<Group type="103" groupAlignment="3" attributes="0">
|
||||
<Component id="saveButton" alignment="3" min="-2" max="-2" attributes="0"/>
|
||||
<Component id="cancelButton" alignment="3" min="-2" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
<EmptySpace max="32767" attributes="0"/>
|
||||
</Group>
|
||||
</Group>
|
||||
</DimensionLayout>
|
||||
</Layout>
|
||||
<SubComponents>
|
||||
<Component class="javax.swing.JTextField" name="categoryTextField">
|
||||
<Events>
|
||||
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="categoryTextFieldActionPerformed"/>
|
||||
</Events>
|
||||
</Component>
|
||||
<Component class="javax.swing.JTextField" name="domainSuffixTextField">
|
||||
<Events>
|
||||
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="domainSuffixTextFieldActionPerformed"/>
|
||||
</Events>
|
||||
</Component>
|
||||
<Component class="javax.swing.JLabel" name="categoryLabel">
|
||||
<Properties>
|
||||
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/url/analytics/Bundle.properties" key="AddEditCategoryDialog.categoryLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
<AuxValues>
|
||||
<AuxValue name="JavaCodeGenerator_VariableLocal" type="java.lang.Boolean" value="true"/>
|
||||
<AuxValue name="JavaCodeGenerator_VariableModifier" type="java.lang.Integer" value="0"/>
|
||||
</AuxValues>
|
||||
</Component>
|
||||
<Component class="javax.swing.JLabel" name="domainSuffixLabel">
|
||||
<Properties>
|
||||
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/url/analytics/Bundle.properties" key="AddEditCategoryDialog.domainSuffixLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
<AuxValues>
|
||||
<AuxValue name="JavaCodeGenerator_VariableLocal" type="java.lang.Boolean" value="true"/>
|
||||
<AuxValue name="JavaCodeGenerator_VariableModifier" type="java.lang.Integer" value="0"/>
|
||||
</AuxValues>
|
||||
</Component>
|
||||
<Component class="javax.swing.JLabel" name="validationLabel">
|
||||
<Properties>
|
||||
<Property name="foreground" type="java.awt.Color" editor="org.netbeans.modules.form.RADConnectionPropertyEditor">
|
||||
<Connection code="java.awt.Color.RED" type="code"/>
|
||||
</Property>
|
||||
<Property name="text" type="java.lang.String" value=" "/>
|
||||
<Property name="toolTipText" type="java.lang.String" value=""/>
|
||||
</Properties>
|
||||
</Component>
|
||||
<Component class="javax.swing.JButton" name="cancelButton">
|
||||
<Properties>
|
||||
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/url/analytics/Bundle.properties" key="AddEditCategoryDialog.cancelButton.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="cancelButtonActionPerformed"/>
|
||||
</Events>
|
||||
<AuxValues>
|
||||
<AuxValue name="JavaCodeGenerator_VariableLocal" type="java.lang.Boolean" value="true"/>
|
||||
<AuxValue name="JavaCodeGenerator_VariableModifier" type="java.lang.Integer" value="0"/>
|
||||
</AuxValues>
|
||||
</Component>
|
||||
<Component class="javax.swing.JButton" name="saveButton">
|
||||
<Properties>
|
||||
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/url/analytics/Bundle.properties" key="AddEditCategoryDialog.saveButton.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="saveButtonActionPerformed"/>
|
||||
</Events>
|
||||
</Component>
|
||||
</SubComponents>
|
||||
</Form>
|
||||
@@ -1,267 +0,0 @@
|
||||
/*
|
||||
* Autopsy Forensic Browser
|
||||
*
|
||||
* Copyright 2021 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.url.analytics;
|
||||
|
||||
import java.util.Set;
|
||||
import org.openide.util.NbBundle.Messages;
|
||||
|
||||
/**
|
||||
* Dialog for adding or editing a custom domain suffix category.
|
||||
*/
|
||||
@Messages({
|
||||
"AddEditCategoryDialog_Edit=Edit Entry",
|
||||
"AddEditCategoryDialog_Add=Add Entry"
|
||||
})
|
||||
class AddEditCategoryDialog extends javax.swing.JDialog {
|
||||
|
||||
private boolean changed = false;
|
||||
private final Set<String> currentSuffixesToUpper;
|
||||
private final DomainCategory currentDomainCategory;
|
||||
|
||||
/**
|
||||
* Main constructor if adding a new domain suffix.
|
||||
*
|
||||
* @param parent The parent frame for this dialog.
|
||||
* @param currentSuffixesToUpper The current domain suffixes to upper case
|
||||
* and trimmed. Used for determining repeats.
|
||||
*/
|
||||
AddEditCategoryDialog(java.awt.Frame parent, Set<String> currentSuffixesToUpper) {
|
||||
this(parent, currentSuffixesToUpper, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Main constructor if editing a domain suffix.
|
||||
*
|
||||
* @param parentThe parent frame for this dialog.
|
||||
* @param currentSuffixesToUpper The current domain suffixes to upper case
|
||||
* and trimmed. Used for determining repeats.
|
||||
* @param currentDomainCategory The domain category being edited. If null,
|
||||
* it will be assumed that a new domain suffix is being added.
|
||||
*/
|
||||
AddEditCategoryDialog(java.awt.Frame parent, Set<String> currentSuffixesToUpper, DomainCategory currentDomainCategory) {
|
||||
super(parent, true);
|
||||
initComponents();
|
||||
this.currentSuffixesToUpper = currentSuffixesToUpper;
|
||||
this.currentDomainCategory = currentDomainCategory;
|
||||
|
||||
// set title based on whether or not we are editing or adding
|
||||
// also don't allow editing of domain suffix if editing
|
||||
if (currentDomainCategory == null) {
|
||||
setTitle(Bundle.AddEditCategoryDialog_Add());
|
||||
domainSuffixTextField.setEditable(true);
|
||||
domainSuffixTextField.setEnabled(true);
|
||||
} else {
|
||||
setTitle(Bundle.AddEditCategoryDialog_Edit());
|
||||
domainSuffixTextField.setEditable(false);
|
||||
domainSuffixTextField.setEnabled(false);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the string value for the name in the input field if Ok pressed or
|
||||
* null if not.
|
||||
* @return The string value for the name in the input field if Ok pressed or
|
||||
* null if not.
|
||||
*/
|
||||
DomainCategory getValue() {
|
||||
return new DomainCategory(domainSuffixTextField.getText().trim(), categoryTextField.getText().trim());
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether or not the value has been changed and saved by the user.
|
||||
* @return Whether or not the value has been changed and saved by the user.
|
||||
*/
|
||||
boolean isChanged() {
|
||||
return changed;
|
||||
}
|
||||
|
||||
/**
|
||||
* When the text field is updated, this method is called.
|
||||
*
|
||||
* @param suffixStr The current domain suffix string in the input.
|
||||
* @param categoryStr The current category string in the input.
|
||||
*/
|
||||
@Messages({
|
||||
"# {0} - maxSuffixLen",
|
||||
"AddEditCategoryDialog_onValueUpdate_badSuffix=Please provide a domain suffix that is no more than {0} characters.",
|
||||
"# {0} - maxCategoryLen",
|
||||
"AddEditCategoryDialog_onValueUpdate_badCategory=Please provide a domain suffix that is no more than {0} characters.",
|
||||
"AddEditCategoryDialog_onValueUpdate_suffixRepeat=Please provide a unique domain suffix.",
|
||||
"AddEditCategoryDialog_onValueUpdate_sameCategory=Please provide a new category for this domain suffix.",})
|
||||
void onValueUpdate(String suffixStr, String categoryStr) {
|
||||
|
||||
String safeSuffixStr = suffixStr == null ? "" : suffixStr;
|
||||
String safeCategoryStr = categoryStr == null ? "" : categoryStr;
|
||||
|
||||
// update input text field if it is not the same.
|
||||
if (!safeCategoryStr.equals(categoryTextField.getText())) {
|
||||
categoryTextField.setText(safeCategoryStr);
|
||||
}
|
||||
|
||||
if (!safeSuffixStr.equals(domainSuffixTextField.getText())) {
|
||||
domainSuffixTextField.setText(safeSuffixStr);
|
||||
}
|
||||
|
||||
String validationMessage = null;
|
||||
if (safeSuffixStr.trim().length() == 0 || safeSuffixStr.trim().length() > WebCategoriesDataModel.getMaxDomainSuffixLength()) {
|
||||
validationMessage = Bundle.AddEditCategoryDialog_onValueUpdate_badSuffix(WebCategoriesDataModel.getMaxCategoryLength());
|
||||
|
||||
} else if (safeCategoryStr.trim().length() == 0 || safeCategoryStr.trim().length() > WebCategoriesDataModel.getMaxCategoryLength()) {
|
||||
validationMessage = Bundle.AddEditCategoryDialog_onValueUpdate_badCategory(WebCategoriesDataModel.getMaxDomainSuffixLength());
|
||||
|
||||
} else if (currentSuffixesToUpper.contains(safeSuffixStr.trim().toUpperCase())) {
|
||||
validationMessage = Bundle.AddEditCategoryDialog_onValueUpdate_suffixRepeat();
|
||||
|
||||
} else if (currentDomainCategory != null
|
||||
&& currentDomainCategory.getCategory() != null
|
||||
&& safeCategoryStr.trim().equals(currentDomainCategory.getCategory().trim())) {
|
||||
|
||||
validationMessage = Bundle.AddEditCategoryDialog_onValueUpdate_sameCategory();
|
||||
}
|
||||
|
||||
saveButton.setEnabled(validationMessage == null);
|
||||
validationLabel.setText(validationMessage == null ? "" : validationMessage);
|
||||
}
|
||||
|
||||
/**
|
||||
* 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() {
|
||||
|
||||
categoryTextField = new javax.swing.JTextField();
|
||||
domainSuffixTextField = new javax.swing.JTextField();
|
||||
javax.swing.JLabel categoryLabel = new javax.swing.JLabel();
|
||||
javax.swing.JLabel domainSuffixLabel = new javax.swing.JLabel();
|
||||
validationLabel = new javax.swing.JLabel();
|
||||
javax.swing.JButton cancelButton = new javax.swing.JButton();
|
||||
saveButton = new javax.swing.JButton();
|
||||
|
||||
setDefaultCloseOperation(javax.swing.WindowConstants.DISPOSE_ON_CLOSE);
|
||||
|
||||
categoryTextField.addActionListener(new java.awt.event.ActionListener() {
|
||||
public void actionPerformed(java.awt.event.ActionEvent evt) {
|
||||
categoryTextFieldActionPerformed(evt);
|
||||
}
|
||||
});
|
||||
|
||||
domainSuffixTextField.addActionListener(new java.awt.event.ActionListener() {
|
||||
public void actionPerformed(java.awt.event.ActionEvent evt) {
|
||||
domainSuffixTextFieldActionPerformed(evt);
|
||||
}
|
||||
});
|
||||
|
||||
categoryLabel.setText(org.openide.util.NbBundle.getMessage(AddEditCategoryDialog.class, "AddEditCategoryDialog.categoryLabel.text")); // NOI18N
|
||||
|
||||
domainSuffixLabel.setText(org.openide.util.NbBundle.getMessage(AddEditCategoryDialog.class, "AddEditCategoryDialog.domainSuffixLabel.text")); // NOI18N
|
||||
|
||||
validationLabel.setForeground(java.awt.Color.RED);
|
||||
validationLabel.setText(" ");
|
||||
validationLabel.setToolTipText("");
|
||||
|
||||
cancelButton.setText(org.openide.util.NbBundle.getMessage(AddEditCategoryDialog.class, "AddEditCategoryDialog.cancelButton.text")); // NOI18N
|
||||
cancelButton.addActionListener(new java.awt.event.ActionListener() {
|
||||
public void actionPerformed(java.awt.event.ActionEvent evt) {
|
||||
cancelButtonActionPerformed(evt);
|
||||
}
|
||||
});
|
||||
|
||||
saveButton.setText(org.openide.util.NbBundle.getMessage(AddEditCategoryDialog.class, "AddEditCategoryDialog.saveButton.text")); // NOI18N
|
||||
saveButton.addActionListener(new java.awt.event.ActionListener() {
|
||||
public void actionPerformed(java.awt.event.ActionEvent evt) {
|
||||
saveButtonActionPerformed(evt);
|
||||
}
|
||||
});
|
||||
|
||||
javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
|
||||
getContentPane().setLayout(layout);
|
||||
layout.setHorizontalGroup(
|
||||
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
.addGroup(layout.createSequentialGroup()
|
||||
.addContainerGap()
|
||||
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
.addComponent(validationLabel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
|
||||
.addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
|
||||
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
.addComponent(domainSuffixLabel)
|
||||
.addComponent(categoryLabel))
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
|
||||
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false)
|
||||
.addComponent(categoryTextField, javax.swing.GroupLayout.DEFAULT_SIZE, 272, Short.MAX_VALUE)
|
||||
.addComponent(domainSuffixTextField)))
|
||||
.addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
|
||||
.addGap(0, 216, Short.MAX_VALUE)
|
||||
.addComponent(saveButton)
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||
.addComponent(cancelButton)))
|
||||
.addContainerGap())
|
||||
);
|
||||
layout.setVerticalGroup(
|
||||
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
.addGroup(layout.createSequentialGroup()
|
||||
.addContainerGap()
|
||||
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING)
|
||||
.addGroup(layout.createSequentialGroup()
|
||||
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
.addComponent(categoryLabel)
|
||||
.addComponent(categoryTextField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
|
||||
.addGap(18, 18, 18)
|
||||
.addComponent(domainSuffixTextField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
|
||||
.addComponent(domainSuffixLabel))
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||
.addComponent(validationLabel)
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
|
||||
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
|
||||
.addComponent(saveButton)
|
||||
.addComponent(cancelButton))
|
||||
.addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
|
||||
);
|
||||
|
||||
pack();
|
||||
}// </editor-fold>//GEN-END:initComponents
|
||||
|
||||
private void saveButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_saveButtonActionPerformed
|
||||
this.changed = true;
|
||||
dispose();
|
||||
}//GEN-LAST:event_saveButtonActionPerformed
|
||||
|
||||
private void cancelButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_cancelButtonActionPerformed
|
||||
this.changed = false;
|
||||
dispose();
|
||||
}//GEN-LAST:event_cancelButtonActionPerformed
|
||||
|
||||
private void domainSuffixTextFieldActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_domainSuffixTextFieldActionPerformed
|
||||
onValueUpdate(domainSuffixTextField.getText(), categoryTextField.getText());
|
||||
}//GEN-LAST:event_domainSuffixTextFieldActionPerformed
|
||||
|
||||
private void categoryTextFieldActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_categoryTextFieldActionPerformed
|
||||
onValueUpdate(domainSuffixTextField.getText(), categoryTextField.getText());
|
||||
}//GEN-LAST:event_categoryTextFieldActionPerformed
|
||||
|
||||
|
||||
// Variables declaration - do not modify//GEN-BEGIN:variables
|
||||
private javax.swing.JTextField categoryTextField;
|
||||
private javax.swing.JTextField domainSuffixTextField;
|
||||
private javax.swing.JButton saveButton;
|
||||
private javax.swing.JLabel validationLabel;
|
||||
// End of variables declaration//GEN-END:variables
|
||||
}
|
||||
@@ -1,13 +0,0 @@
|
||||
WebCategoryOptionsController_title=Custom Web Categories
|
||||
WebCategoryOptionsController_keywords=Custom Web Categories
|
||||
AddEditCategoryDialog.categoryLabel.text=Category:
|
||||
AddEditCategoryDialog.domainSuffixLabel.text=Domain Suffix:
|
||||
AddEditCategoryDialog.saveButton.text=Save
|
||||
AddEditCategoryDialog.cancelButton.text=Cancel
|
||||
WebCategoriesOptionsPanel.panelDescription.text=This module allows you to find web categories based on host name.
|
||||
WebCategoriesOptionsPanel.categoriesTitle.text=Categories:
|
||||
WebCategoriesOptionsPanel.newEntryButton.text=New Entry
|
||||
WebCategoriesOptionsPanel.editEntryButton.text=Edit Entry
|
||||
WebCategoriesOptionsPanel.deleteEntryButton.text=Delete Entry
|
||||
WebCategoriesOptionsPanel.importSetButton.text=Import Set
|
||||
WebCategoriesOptionsPanel.exportSetButton.text=Export Set
|
||||
@@ -1,19 +0,0 @@
|
||||
# {0} - maxCategoryLen
|
||||
AddEditCategoryDialog_onValueUpdate_badCategory=Please provide a domain suffix that is no more than {0} characters.
|
||||
# {0} - maxSuffixLen
|
||||
AddEditCategoryDialog_onValueUpdate_badSuffix=Please provide a domain suffix that is no more than {0} characters.
|
||||
AddEditCategoryDialog_onValueUpdate_sameCategory=Please provide a new category for this domain suffix.
|
||||
AddEditCategoryDialog_onValueUpdate_suffixRepeat=Please provide a unique domain suffix.
|
||||
WebCategoryOptionsController_title=Custom Web Categories
|
||||
WebCategoryOptionsController_keywords=Custom Web Categories
|
||||
AddEditCategoryDialog.categoryLabel.text=Category:
|
||||
AddEditCategoryDialog.domainSuffixLabel.text=Domain Suffix:
|
||||
AddEditCategoryDialog.saveButton.text=Save
|
||||
AddEditCategoryDialog.cancelButton.text=Cancel
|
||||
WebCategoriesOptionsPanel.panelDescription.text=This module allows you to find web categories based on host name.
|
||||
WebCategoriesOptionsPanel.categoriesTitle.text=Categories:
|
||||
WebCategoriesOptionsPanel.newEntryButton.text=New Entry
|
||||
WebCategoriesOptionsPanel.editEntryButton.text=Edit Entry
|
||||
WebCategoriesOptionsPanel.deleteEntryButton.text=Delete Entry
|
||||
WebCategoriesOptionsPanel.importSetButton.text=Import Set
|
||||
WebCategoriesOptionsPanel.exportSetButton.text=Export Set
|
||||
@@ -1,88 +0,0 @@
|
||||
/*
|
||||
* Autopsy Forensic Browser
|
||||
*
|
||||
* Copyright 2021 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.url.analytics;
|
||||
|
||||
import java.sql.SQLException;
|
||||
import java.util.logging.Level;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.openide.util.lookup.ServiceProvider;
|
||||
import org.sleuthkit.autopsy.coreutils.Logger;
|
||||
|
||||
/**
|
||||
* A DomainCategoryProvider for custom web categories.
|
||||
*/
|
||||
@ServiceProvider(service = DomainCategorizer.class)
|
||||
public class CustomWebCategorizer implements DomainCategorizer {
|
||||
|
||||
private static final Logger logger = Logger.getLogger(CustomWebCategorizer.class.getName());
|
||||
|
||||
private final WebCategoriesDataModel dataModel;
|
||||
|
||||
/**
|
||||
* Constructor accepting a custom WebCategoriesDataModel.
|
||||
*
|
||||
* @param dataModel The WebCategoriesDataModel to use as a data model.
|
||||
*/
|
||||
CustomWebCategorizer(WebCategoriesDataModel dataModel) {
|
||||
this.dataModel = dataModel;
|
||||
}
|
||||
|
||||
/**
|
||||
* No parameter constructor that uses the singleton instance of the
|
||||
* WebCategoriesDataModel.
|
||||
*
|
||||
*/
|
||||
public CustomWebCategorizer() {
|
||||
this(WebCategoriesDataModel.getInstance());
|
||||
}
|
||||
|
||||
@Override
|
||||
public DomainCategory getCategory(String domain, String host) throws DomainCategorizerException {
|
||||
if (!dataModel.isInitialized()) {
|
||||
return null;
|
||||
}
|
||||
String hostToUse = (StringUtils.isBlank(host)) ? domain : host;
|
||||
if (StringUtils.isBlank(hostToUse)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
hostToUse = hostToUse.toLowerCase();
|
||||
|
||||
try {
|
||||
return dataModel.getMatchingRecord(hostToUse);
|
||||
} catch (SQLException ex) {
|
||||
logger.log(Level.WARNING, "There was an error while retrieving data for: " + hostToUse, ex);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void initialize() throws DomainCategorizerException {
|
||||
try {
|
||||
dataModel.initialize();
|
||||
} catch (SQLException ex) {
|
||||
throw new DomainCategorizerException("Unable to initialize.", ex);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() throws Exception {
|
||||
dataModel.close();
|
||||
}
|
||||
}
|
||||
@@ -1,509 +0,0 @@
|
||||
/*
|
||||
* Autopsy Forensic Browser
|
||||
*
|
||||
* Copyright 2021 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.url.analytics;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonCreator;
|
||||
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
import com.fasterxml.jackson.core.type.TypeReference;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Paths;
|
||||
import java.sql.Connection;
|
||||
import java.sql.DriverManager;
|
||||
import java.sql.PreparedStatement;
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
import java.sql.Statement;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.IntStream;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.apache.commons.lang3.tuple.Pair;
|
||||
import org.openide.modules.InstalledFileLocator;
|
||||
|
||||
/**
|
||||
* Provides the data model for exporting, importing and CRUD operations on
|
||||
* custom web categories.
|
||||
*/
|
||||
class WebCategoriesDataModel implements AutoCloseable {
|
||||
|
||||
/**
|
||||
* DTO to be used with jackson when converting to and from exported content.
|
||||
*/
|
||||
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||
static class CustomCategorizationJsonDto {
|
||||
|
||||
private final String category;
|
||||
private final List<String> domains;
|
||||
|
||||
/**
|
||||
* Main constructor.
|
||||
*
|
||||
* @param category The category.
|
||||
* @param domains The list of host suffixes in this category.
|
||||
*/
|
||||
@JsonCreator
|
||||
CustomCategorizationJsonDto(
|
||||
@JsonProperty("category") String category,
|
||||
@JsonProperty("domains") List<String> domains) {
|
||||
this.category = category;
|
||||
this.domains = domains == null
|
||||
? Collections.emptyList()
|
||||
: new ArrayList<>(domains);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the category.
|
||||
*
|
||||
* @return The category.
|
||||
*/
|
||||
String getCategory() {
|
||||
return category;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the list of domain suffixes in this category.
|
||||
*
|
||||
* @return The list of domain suffixes in this category.
|
||||
*/
|
||||
List<String> getDomains() {
|
||||
return domains;
|
||||
}
|
||||
}
|
||||
|
||||
private static final int MAX_CAT_SIZE = 300;
|
||||
private static final int MAX_DOMAIN_SIZE = 255;
|
||||
|
||||
private static final String ROOT_FOLDER = "DomainCategorization";
|
||||
private static final String FILE_REL_PATH = "custom_list.db";
|
||||
private static final String JDBC_SQLITE_PREFIX = "jdbc:sqlite:";
|
||||
private static final String TABLE_NAME = "domain_suffix";
|
||||
private static final String SUFFIX_COLUMN = "suffix";
|
||||
private static final String CATEGORY_COLUMN = "category";
|
||||
|
||||
private static final Logger logger = Logger.getLogger(WebCategoriesDataModel.class.getName());
|
||||
private static WebCategoriesDataModel instance;
|
||||
|
||||
/**
|
||||
* Returns the maximum string length of a domain suffix.
|
||||
*
|
||||
* @return The maximum string length of a domain suffix.
|
||||
*/
|
||||
static int getMaxDomainSuffixLength() {
|
||||
return MAX_DOMAIN_SIZE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the maximum string length of a category.
|
||||
*
|
||||
* @return The maximum string length of a category.
|
||||
*/
|
||||
static int getMaxCategoryLength() {
|
||||
return MAX_DOMAIN_SIZE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the default path for where custom domain categorization exists.
|
||||
*
|
||||
* @return The path or null if the path cannot be reconciled.
|
||||
*/
|
||||
private static File getDefaultPath() {
|
||||
File dir = InstalledFileLocator.getDefault().locate(ROOT_FOLDER, WebCategoriesDataModel.class.getPackage().getName(), false);
|
||||
if (dir == null || !dir.exists()) {
|
||||
logger.log(Level.WARNING, String.format("Unable to find file %s with InstalledFileLocator", ROOT_FOLDER));
|
||||
return null;
|
||||
}
|
||||
|
||||
return Paths.get(dir.getAbsolutePath(), FILE_REL_PATH).toFile();
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates the normalized category string to be inserted into the
|
||||
* database.
|
||||
*
|
||||
* @param category The category.
|
||||
* @return The normalized string.
|
||||
*/
|
||||
private static String getNormalizedCategory(String category) {
|
||||
if (category == null) {
|
||||
return "";
|
||||
}
|
||||
|
||||
return category.trim().substring(0, Math.min(category.length(), MAX_CAT_SIZE));
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates the normalized domain suffix string to be inserted into the
|
||||
* database.
|
||||
*
|
||||
* @param domainSuffix The domain suffix.
|
||||
* @return The normalized string.
|
||||
*/
|
||||
private static String getNormalizedSuffix(String domainSuffix) {
|
||||
if (domainSuffix == null) {
|
||||
return "";
|
||||
}
|
||||
|
||||
return domainSuffix.trim().substring(0, Math.min(domainSuffix.length(), MAX_DOMAIN_SIZE)).toLowerCase();
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves a singleton instance of this class.
|
||||
*
|
||||
* @return The singleton instance of this class.
|
||||
*/
|
||||
static WebCategoriesDataModel getInstance() {
|
||||
if (instance == null) {
|
||||
instance = new WebCategoriesDataModel();
|
||||
}
|
||||
|
||||
return instance;
|
||||
}
|
||||
|
||||
private final File sqlitePath;
|
||||
private Connection dbConn = null;
|
||||
|
||||
/**
|
||||
* Constructor used to create singleton instance.
|
||||
*/
|
||||
private WebCategoriesDataModel() {
|
||||
this(getDefaultPath());
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor that accepts a variable path for the custom sqlite database
|
||||
* for custom domain categories.
|
||||
*
|
||||
* @param sqlitePath The path.
|
||||
*/
|
||||
WebCategoriesDataModel(File sqlitePath) {
|
||||
this.sqlitePath = sqlitePath;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a sqlite jdbc connection.
|
||||
*
|
||||
* @throws SQLException
|
||||
*/
|
||||
synchronized void initialize() throws SQLException {
|
||||
String url = JDBC_SQLITE_PREFIX + sqlitePath.getAbsolutePath();
|
||||
if (this.dbConn != null) {
|
||||
this.dbConn.close();
|
||||
this.dbConn = null;
|
||||
}
|
||||
|
||||
this.dbConn = DriverManager.getConnection(url);
|
||||
|
||||
// speed up operations by turning off WAL
|
||||
try (Statement turnOffWal = dbConn.createStatement()) {
|
||||
turnOffWal.execute("PRAGMA journal_mode=OFF");
|
||||
}
|
||||
|
||||
// create table if it doesn't exist
|
||||
try (Statement createDomainsTable = dbConn.createStatement()) {
|
||||
createDomainsTable.execute(
|
||||
" CREATE TABLE IF NOT EXISTS " + TABLE_NAME + " (\n"
|
||||
+ " " + SUFFIX_COLUMN + " VARCHAR(" + MAX_DOMAIN_SIZE + ") PRIMARY KEY,\n"
|
||||
+ " " + CATEGORY_COLUMN + " VARCHAR(" + MAX_CAT_SIZE + ")\n"
|
||||
+ " ) WITHOUT ROWID");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if initialized.
|
||||
*
|
||||
* @return True if initialized.
|
||||
*/
|
||||
synchronized boolean isInitialized() {
|
||||
return this.dbConn != null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Imports json file replacing any data in this database.
|
||||
*
|
||||
* @param jsonInput The json file to import.
|
||||
* @throws IOException
|
||||
* @throws SQLException
|
||||
*/
|
||||
synchronized void importJson(File jsonInput) throws IOException, SQLException {
|
||||
if (jsonInput == null) {
|
||||
logger.log(Level.WARNING, "No valid file provided.");
|
||||
return;
|
||||
}
|
||||
|
||||
if (!isInitialized()) {
|
||||
initialize();
|
||||
}
|
||||
|
||||
ObjectMapper mapper = new ObjectMapper();
|
||||
List<CustomCategorizationJsonDto> customCategorizations = mapper.readValue(jsonInput, new TypeReference<List<CustomCategorizationJsonDto>>() {
|
||||
});
|
||||
|
||||
customCategorizations = customCategorizations == null ? Collections.emptyList() : customCategorizations;
|
||||
|
||||
// insert all records as a batch for speed purposes
|
||||
try (PreparedStatement domainInsert = dbConn.prepareStatement(
|
||||
"INSERT OR REPLACE INTO " + TABLE_NAME + "(" + SUFFIX_COLUMN + ", " + CATEGORY_COLUMN + ") VALUES (?, ?)", Statement.NO_GENERATED_KEYS)) {
|
||||
|
||||
for (int i = 0; i < customCategorizations.size(); i++) {
|
||||
CustomCategorizationJsonDto category = customCategorizations.get(i);
|
||||
if (category == null || category.getDomains() == null || category.getCategory() == null) {
|
||||
logger.log(Level.WARNING, String.format("Could not process item in file: %s at index: %d", jsonInput.getAbsolutePath(), i));
|
||||
continue;
|
||||
}
|
||||
|
||||
String categoryStr = getNormalizedCategory(category.getCategory());
|
||||
|
||||
for (int listIdx = 0; listIdx < category.getDomains().size(); i++) {
|
||||
String domain = category.getDomains().get(listIdx);
|
||||
if (domain == null) {
|
||||
logger.log(Level.WARNING, String.format("Could not process domain at idx: %d in category %s for file %s",
|
||||
listIdx, categoryStr, jsonInput.getAbsolutePath()));
|
||||
}
|
||||
|
||||
domainInsert.setString(1, getNormalizedSuffix(domain));
|
||||
domainInsert.setString(2, categoryStr);
|
||||
domainInsert.addBatch();
|
||||
}
|
||||
}
|
||||
|
||||
domainInsert.executeBatch();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Exports current database to a json file.
|
||||
*
|
||||
* @param jsonOutput The output file.
|
||||
* @throws SQLException
|
||||
* @throws IOException
|
||||
*/
|
||||
synchronized void exportToJson(File jsonOutput) throws SQLException, IOException {
|
||||
if (jsonOutput == null) {
|
||||
logger.log(Level.WARNING, "Null file provided.");
|
||||
return;
|
||||
}
|
||||
|
||||
if (!isInitialized()) {
|
||||
initialize();
|
||||
}
|
||||
|
||||
// retrieve items from the database
|
||||
List<Pair<String, String>> categoryDomains = new ArrayList<>();
|
||||
try (Statement domainSelect = dbConn.createStatement();
|
||||
ResultSet resultSet = domainSelect.executeQuery(
|
||||
"SELECT " + SUFFIX_COLUMN + ", " + CATEGORY_COLUMN + " FROM " + TABLE_NAME)) {
|
||||
|
||||
while (resultSet.next()) {
|
||||
categoryDomains.add(Pair.of(resultSet.getString(CATEGORY_COLUMN), resultSet.getString(SUFFIX_COLUMN)));
|
||||
}
|
||||
}
|
||||
|
||||
// aggregate data appropriately into CustomCategorizationJsonDto
|
||||
List<CustomCategorizationJsonDto> categories
|
||||
= categoryDomains.stream()
|
||||
.collect(Collectors.toMap(
|
||||
p -> p.getKey(),
|
||||
p -> new ArrayList<>(Arrays.asList(p.getValue())),
|
||||
(p1, p2) -> {
|
||||
p1.addAll(p2);
|
||||
return p1;
|
||||
}
|
||||
))
|
||||
.entrySet().stream()
|
||||
.map(entry -> new CustomCategorizationJsonDto(entry.getKey(), entry.getValue()))
|
||||
.collect(Collectors.toList());
|
||||
|
||||
// write to disk
|
||||
ObjectMapper mapper = new ObjectMapper();
|
||||
mapper.writeValue(jsonOutput, categories);
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete a record from the database.
|
||||
*
|
||||
* @param domainSuffix The domain suffix of the item to delete.
|
||||
* @return Whether or not the operation actually deleted something.
|
||||
* @throws SQLException
|
||||
* @throws IllegalArgumentException
|
||||
*/
|
||||
synchronized boolean deleteRecord(String domainSuffix) throws SQLException, IllegalArgumentException {
|
||||
if (StringUtils.isBlank(domainSuffix)) {
|
||||
throw new IllegalArgumentException("Expected non-empty domain suffix");
|
||||
}
|
||||
|
||||
if (!isInitialized()) {
|
||||
initialize();
|
||||
}
|
||||
|
||||
try (PreparedStatement suffixDelete = dbConn.prepareStatement(
|
||||
"DELETE FROM " + TABLE_NAME + " WHERE LOWER(" + SUFFIX_COLUMN + ") = LOWER(?)", Statement.RETURN_GENERATED_KEYS);) {
|
||||
|
||||
suffixDelete.setString(1, getNormalizedSuffix(domainSuffix));
|
||||
return suffixDelete.executeUpdate() > 0;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Inserts or updates the entry for the given domain suffix.
|
||||
*
|
||||
* @param entry The domain suffix and category.
|
||||
* @return True if successfully inserted/updated.
|
||||
* @throws SQLException
|
||||
* @throws IllegalStateException
|
||||
* @throws IllegalArgumentException
|
||||
*/
|
||||
synchronized boolean insertUpdateSuffix(DomainCategory entry) throws SQLException, IllegalStateException, IllegalArgumentException {
|
||||
if (entry == null || StringUtils.isBlank(entry.getCategory()) || StringUtils.isBlank(entry.getHostSuffix())) {
|
||||
throw new IllegalArgumentException("Expected non-empty category and domain suffix.");
|
||||
}
|
||||
|
||||
if (!isInitialized()) {
|
||||
initialize();
|
||||
}
|
||||
|
||||
try (PreparedStatement insertUpdate = dbConn.prepareStatement(
|
||||
"INSERT OR REPLACE INTO " + TABLE_NAME + "(" + SUFFIX_COLUMN + ", " + CATEGORY_COLUMN + ") VALUES (?, ?)",
|
||||
Statement.RETURN_GENERATED_KEYS)) {
|
||||
|
||||
insertUpdate.setString(1, getNormalizedSuffix(entry.getHostSuffix()));
|
||||
insertUpdate.setString(1, getNormalizedCategory(entry.getCategory()));
|
||||
return insertUpdate.executeUpdate() > 0;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Return all records in the database.
|
||||
*
|
||||
* @return The list of domain suffixes and their categories.
|
||||
* @throws SQLException
|
||||
*/
|
||||
List<DomainCategory> getRecords() throws SQLException {
|
||||
if (!isInitialized()) {
|
||||
initialize();
|
||||
}
|
||||
|
||||
List<DomainCategory> entries = new ArrayList<>();
|
||||
|
||||
try (Statement domainSelect = dbConn.createStatement();
|
||||
ResultSet resultSet = domainSelect.executeQuery(
|
||||
"SELECT " + SUFFIX_COLUMN + ", " + CATEGORY_COLUMN + " FROM " + TABLE_NAME + "")) {
|
||||
|
||||
while (resultSet.next()) {
|
||||
entries.add(new DomainCategory(
|
||||
resultSet.getString(SUFFIX_COLUMN),
|
||||
resultSet.getString(CATEGORY_COLUMN)));
|
||||
}
|
||||
}
|
||||
return entries;
|
||||
|
||||
}
|
||||
|
||||
// get the suffix and category from the main table and gets the longest matching suffix.
|
||||
private static final String BASE_QUERY_FMT_STR
|
||||
= "SELECT " + SUFFIX_COLUMN + ", " + CATEGORY_COLUMN + " FROM " + TABLE_NAME
|
||||
+ " WHERE suffix IN (%s) ORDER BY LENGTH(" + SUFFIX_COLUMN + ") DESC LIMIT 1";
|
||||
|
||||
/**
|
||||
* Retrieves the longest matching domain suffix and category matching the
|
||||
* list of suffixes or null if no item can be found.
|
||||
*
|
||||
* @param suffixes The list of suffixes.
|
||||
* @return The longest matching entry or null if no entry found.
|
||||
* @throws SQLException
|
||||
*/
|
||||
synchronized DomainCategory getLongestSuffixRecord(List<String> suffixes) throws SQLException {
|
||||
if (suffixes == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (!isInitialized()) {
|
||||
initialize();
|
||||
}
|
||||
|
||||
String questionMarks = IntStream.range(0, suffixes.size())
|
||||
.mapToObj((num) -> "?")
|
||||
.collect(Collectors.joining(","));
|
||||
|
||||
try (PreparedStatement stmt = dbConn.prepareStatement(String.format(BASE_QUERY_FMT_STR, questionMarks))) {
|
||||
for (int i = 0; i < suffixes.size(); i++) {
|
||||
stmt.setString(i + 1, suffixes.get(i));
|
||||
}
|
||||
|
||||
try (ResultSet resultSet = stmt.executeQuery()) {
|
||||
if (resultSet.next()) {
|
||||
String suffix = resultSet.getString(SUFFIX_COLUMN);
|
||||
String category = resultSet.getString(CATEGORY_COLUMN);
|
||||
return new DomainCategory(suffix, category);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the longest matching domain suffix and category matching the
|
||||
* list of suffixes or null if no item can be found.
|
||||
*
|
||||
* @param host The host name.
|
||||
* @return The longest matching entry or null if no entry found.
|
||||
* @throws SQLException
|
||||
*/
|
||||
DomainCategory getMatchingRecord(String host) throws SQLException {
|
||||
return getLongestSuffixRecord(getSuffixes(host));
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves all the possible suffixes that could be tracked. For instance,
|
||||
* if the host was "chatenabled.mail.google.com", the list should be
|
||||
* ["chatenabled.mail.google.com", "mail.google.com", "google.com", "com"].
|
||||
*
|
||||
* @param host The host.
|
||||
* @return The possible suffixes.
|
||||
*/
|
||||
private List<String> getSuffixes(String host) {
|
||||
if (host == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
List<String> hostTokens = Arrays.asList(host.split("\\."));
|
||||
List<String> hostSegmentations = new ArrayList<>();
|
||||
|
||||
for (int i = 0; i < hostTokens.size(); i++) {
|
||||
String searchString = String.join(".", hostTokens.subList(i, hostTokens.size()));
|
||||
hostSegmentations.add(searchString);
|
||||
}
|
||||
|
||||
return hostSegmentations;
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized void close() throws Exception {
|
||||
dbConn.close();
|
||||
dbConn = null;
|
||||
}
|
||||
}
|
||||
@@ -1,86 +0,0 @@
|
||||
/*
|
||||
* Autopsy Forensic Browser
|
||||
*
|
||||
* Copyright 2021 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.url.analytics;
|
||||
|
||||
import java.beans.PropertyChangeListener;
|
||||
import javax.swing.JComponent;
|
||||
import org.netbeans.spi.options.OptionsPanelController;
|
||||
import org.openide.util.HelpCtx;
|
||||
import org.openide.util.Lookup;
|
||||
|
||||
/**
|
||||
* The options panel controller that registers and displays the option panel for
|
||||
* custom web categories.
|
||||
*/
|
||||
@OptionsPanelController.TopLevelRegistration(categoryName = "#WebCategoryOptionsController_title",
|
||||
iconBase = "org/sleuthkit/autopsy/corecomponents/checkbox32.png",
|
||||
position = 21,
|
||||
keywords = "#WebCategoryOptionsController_keywords",
|
||||
keywordsCategory = "Custom Web Categories")
|
||||
public class WebCategoriesOptionsController extends OptionsPanelController {
|
||||
|
||||
private final WebCategoriesDataModel dataModel = WebCategoriesDataModel.getInstance();
|
||||
private final WebCategoriesOptionsPanel panel = new WebCategoriesOptionsPanel(dataModel);
|
||||
|
||||
@Override
|
||||
public void update() {
|
||||
panel.refresh();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void applyChanges() {
|
||||
// NO OP since saves happen whenever there is a change.
|
||||
}
|
||||
|
||||
@Override
|
||||
public void cancel() {
|
||||
// NO OP since saves happen whenever there is a change.
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isValid() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isChanged() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public JComponent getComponent(Lookup masterLookup) {
|
||||
return panel;
|
||||
}
|
||||
|
||||
@Override
|
||||
public HelpCtx getHelpCtx() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addPropertyChangeListener(PropertyChangeListener l) {
|
||||
// NO OP since saves happen whenever there is a change.
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removePropertyChangeListener(PropertyChangeListener l) {
|
||||
// NO OP since saves happen whenever there is a change.
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,195 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
|
||||
<Form version="1.8" maxVersion="1.9" type="org.netbeans.modules.form.forminfo.JPanelFormInfo">
|
||||
<AuxValues>
|
||||
<AuxValue name="FormSettings_autoResourcing" type="java.lang.Integer" value="0"/>
|
||||
<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="false"/>
|
||||
<AuxValue name="FormSettings_i18nAutoMode" type="java.lang.Boolean" value="false"/>
|
||||
<AuxValue name="FormSettings_layoutCodeTarget" type="java.lang.Integer" value="1"/>
|
||||
<AuxValue name="FormSettings_listenerGenerationStyle" type="java.lang.Integer" value="0"/>
|
||||
<AuxValue name="FormSettings_variablesLocal" type="java.lang.Boolean" value="false"/>
|
||||
<AuxValue name="FormSettings_variablesModifier" type="java.lang.Integer" value="2"/>
|
||||
<AuxValue name="designerSize" type="java.awt.Dimension" value="-84,-19,0,5,115,114,0,18,106,97,118,97,46,97,119,116,46,68,105,109,101,110,115,105,111,110,65,-114,-39,-41,-84,95,68,20,2,0,2,73,0,6,104,101,105,103,104,116,73,0,5,119,105,100,116,104,120,112,0,0,2,106,0,0,3,37"/>
|
||||
</AuxValues>
|
||||
|
||||
<Layout class="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout"/>
|
||||
<SubComponents>
|
||||
<Component class="javax.swing.JLabel" name="panelDescription">
|
||||
<Properties>
|
||||
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/url/analytics/Bundle.properties" key="WebCategoriesOptionsPanel.panelDescription.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</Property>
|
||||
<Property name="border" type="javax.swing.border.Border" editor="org.netbeans.modules.form.editors2.BorderEditor">
|
||||
<Border info="org.netbeans.modules.form.compat2.border.CompoundBorderInfo">
|
||||
<CompoundBorder>
|
||||
<Border PropertyName="outside" info="org.netbeans.modules.form.compat2.border.EtchedBorderInfo">
|
||||
<EtchetBorder/>
|
||||
</Border>
|
||||
<Border PropertyName="inside" info="org.netbeans.modules.form.compat2.border.EmptyBorderInfo">
|
||||
<EmptyBorder bottom="5" left="5" right="5" top="5"/>
|
||||
</Border>
|
||||
</CompoundBorder>
|
||||
</Border>
|
||||
</Property>
|
||||
</Properties>
|
||||
<AuxValues>
|
||||
<AuxValue name="JavaCodeGenerator_VariableLocal" type="java.lang.Boolean" value="true"/>
|
||||
<AuxValue name="JavaCodeGenerator_VariableModifier" type="java.lang.Integer" value="0"/>
|
||||
</AuxValues>
|
||||
<Constraints>
|
||||
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
|
||||
<GridBagConstraints gridX="-1" gridY="-1" gridWidth="3" gridHeight="1" fill="3" ipadX="0" ipadY="0" insetsTop="10" insetsLeft="10" insetsBottom="10" insetsRight="0" anchor="21" weightX="0.0" weightY="0.0"/>
|
||||
</Constraint>
|
||||
</Constraints>
|
||||
</Component>
|
||||
<Component class="javax.swing.JLabel" name="categoriesTitle">
|
||||
<Properties>
|
||||
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/url/analytics/Bundle.properties" key="WebCategoriesOptionsPanel.categoriesTitle.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
<AuxValues>
|
||||
<AuxValue name="JavaCodeGenerator_VariableLocal" type="java.lang.Boolean" value="true"/>
|
||||
<AuxValue name="JavaCodeGenerator_VariableModifier" type="java.lang.Integer" value="0"/>
|
||||
</AuxValues>
|
||||
<Constraints>
|
||||
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
|
||||
<GridBagConstraints gridX="0" gridY="1" gridWidth="3" gridHeight="1" fill="0" ipadX="0" ipadY="0" insetsTop="0" insetsLeft="10" insetsBottom="0" insetsRight="0" anchor="21" weightX="0.0" weightY="0.0"/>
|
||||
</Constraint>
|
||||
</Constraints>
|
||||
</Component>
|
||||
<Component class="javax.swing.JButton" name="newEntryButton">
|
||||
<Properties>
|
||||
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/url/analytics/Bundle.properties" key="WebCategoriesOptionsPanel.newEntryButton.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="newEntryButtonActionPerformed"/>
|
||||
</Events>
|
||||
<AuxValues>
|
||||
<AuxValue name="JavaCodeGenerator_VariableLocal" type="java.lang.Boolean" value="true"/>
|
||||
<AuxValue name="JavaCodeGenerator_VariableModifier" type="java.lang.Integer" value="0"/>
|
||||
</AuxValues>
|
||||
<Constraints>
|
||||
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
|
||||
<GridBagConstraints gridX="0" gridY="3" gridWidth="1" gridHeight="1" fill="0" ipadX="0" ipadY="0" insetsTop="0" insetsLeft="10" insetsBottom="5" insetsRight="5" anchor="21" weightX="0.0" weightY="0.0"/>
|
||||
</Constraint>
|
||||
</Constraints>
|
||||
</Component>
|
||||
<Component class="javax.swing.JButton" name="editEntryButton">
|
||||
<Properties>
|
||||
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/url/analytics/Bundle.properties" key="WebCategoriesOptionsPanel.editEntryButton.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="editEntryButtonActionPerformed"/>
|
||||
</Events>
|
||||
<Constraints>
|
||||
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
|
||||
<GridBagConstraints gridX="1" gridY="3" gridWidth="1" gridHeight="1" fill="0" ipadX="0" ipadY="0" insetsTop="0" insetsLeft="0" insetsBottom="5" insetsRight="5" anchor="21" weightX="0.0" weightY="0.0"/>
|
||||
</Constraint>
|
||||
</Constraints>
|
||||
</Component>
|
||||
<Component class="javax.swing.JButton" name="deleteEntryButton">
|
||||
<Properties>
|
||||
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/url/analytics/Bundle.properties" key="WebCategoriesOptionsPanel.deleteEntryButton.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="deleteEntryButtonActionPerformed"/>
|
||||
</Events>
|
||||
<Constraints>
|
||||
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
|
||||
<GridBagConstraints gridX="2" gridY="3" gridWidth="1" gridHeight="1" fill="0" ipadX="0" ipadY="0" insetsTop="0" insetsLeft="0" insetsBottom="5" insetsRight="5" anchor="21" weightX="0.0" weightY="0.0"/>
|
||||
</Constraint>
|
||||
</Constraints>
|
||||
</Component>
|
||||
<Component class="javax.swing.JButton" name="importSetButton">
|
||||
<Properties>
|
||||
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/url/analytics/Bundle.properties" key="WebCategoriesOptionsPanel.importSetButton.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="importSetButtonActionPerformed"/>
|
||||
</Events>
|
||||
<AuxValues>
|
||||
<AuxValue name="JavaCodeGenerator_VariableLocal" type="java.lang.Boolean" value="true"/>
|
||||
<AuxValue name="JavaCodeGenerator_VariableModifier" type="java.lang.Integer" value="0"/>
|
||||
</AuxValues>
|
||||
<Constraints>
|
||||
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
|
||||
<GridBagConstraints gridX="0" gridY="4" gridWidth="1" gridHeight="1" fill="0" ipadX="0" ipadY="0" insetsTop="0" insetsLeft="10" insetsBottom="5" insetsRight="5" anchor="21" weightX="0.0" weightY="0.0"/>
|
||||
</Constraint>
|
||||
</Constraints>
|
||||
</Component>
|
||||
<Component class="javax.swing.JButton" name="exportSetButton">
|
||||
<Properties>
|
||||
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/url/analytics/Bundle.properties" key="WebCategoriesOptionsPanel.exportSetButton.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="exportSetButtonActionPerformed"/>
|
||||
</Events>
|
||||
<AuxValues>
|
||||
<AuxValue name="JavaCodeGenerator_VariableLocal" type="java.lang.Boolean" value="true"/>
|
||||
<AuxValue name="JavaCodeGenerator_VariableModifier" type="java.lang.Integer" value="0"/>
|
||||
</AuxValues>
|
||||
<Constraints>
|
||||
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
|
||||
<GridBagConstraints gridX="1" gridY="4" gridWidth="1" gridHeight="1" fill="0" ipadX="0" ipadY="0" insetsTop="0" insetsLeft="0" insetsBottom="5" insetsRight="5" anchor="21" weightX="0.0" weightY="0.0"/>
|
||||
</Constraint>
|
||||
</Constraints>
|
||||
</Component>
|
||||
<Container class="javax.swing.JPanel" name="bottomStrut">
|
||||
<AuxValues>
|
||||
<AuxValue name="JavaCodeGenerator_VariableLocal" type="java.lang.Boolean" value="true"/>
|
||||
<AuxValue name="JavaCodeGenerator_VariableModifier" type="java.lang.Integer" value="0"/>
|
||||
</AuxValues>
|
||||
<Constraints>
|
||||
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
|
||||
<GridBagConstraints gridX="3" gridY="5" gridWidth="1" gridHeight="1" fill="3" ipadX="0" ipadY="0" insetsTop="0" insetsLeft="0" insetsBottom="0" insetsRight="0" anchor="10" weightX="1.0" weightY="1.0"/>
|
||||
</Constraint>
|
||||
</Constraints>
|
||||
|
||||
<Layout class="org.netbeans.modules.form.compat2.layouts.DesignFlowLayout"/>
|
||||
</Container>
|
||||
<Container class="javax.swing.JScrollPane" name="tableScrollPane">
|
||||
<Properties>
|
||||
<Property name="maximumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
|
||||
<Dimension value="[325, 32767]"/>
|
||||
</Property>
|
||||
<Property name="minimumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
|
||||
<Dimension value="[325, 300]"/>
|
||||
</Property>
|
||||
<Property name="preferredSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
|
||||
<Dimension value="[325, 400]"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
<Constraints>
|
||||
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
|
||||
<GridBagConstraints gridX="0" gridY="2" gridWidth="3" gridHeight="1" fill="0" ipadX="0" ipadY="0" insetsTop="2" insetsLeft="10" insetsBottom="5" insetsRight="0" anchor="17" weightX="0.0" weightY="0.0"/>
|
||||
</Constraint>
|
||||
</Constraints>
|
||||
|
||||
<Layout class="org.netbeans.modules.form.compat2.layouts.support.JScrollPaneSupportLayout"/>
|
||||
<SubComponents>
|
||||
<Container class="javax.swing.JPanel" name="categoryTablePanel">
|
||||
<AuxValues>
|
||||
<AuxValue name="JavaCodeGenerator_CreateCodeCustom" type="java.lang.String" value="categoryTable"/>
|
||||
<AuxValue name="JavaCodeGenerator_VariableLocal" type="java.lang.Boolean" value="true"/>
|
||||
<AuxValue name="JavaCodeGenerator_VariableModifier" type="java.lang.Integer" value="0"/>
|
||||
</AuxValues>
|
||||
|
||||
<Layout class="org.netbeans.modules.form.compat2.layouts.DesignFlowLayout"/>
|
||||
</Container>
|
||||
</SubComponents>
|
||||
</Container>
|
||||
</SubComponents>
|
||||
</Form>
|
||||
@@ -1,322 +0,0 @@
|
||||
/*
|
||||
* Autopsy Forensic Browser
|
||||
*
|
||||
* Copyright 2021 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.url.analytics;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.sql.SQLException;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
import javax.swing.JFileChooser;
|
||||
import javax.swing.JFrame;
|
||||
import javax.swing.JOptionPane;
|
||||
import javax.swing.filechooser.FileNameExtensionFilter;
|
||||
import org.openide.util.NbBundle.Messages;
|
||||
import org.sleuthkit.autopsy.corecomponents.OptionsPanel;
|
||||
import org.sleuthkit.autopsy.ingest.IngestModuleGlobalSettingsPanel;
|
||||
|
||||
// TODO Turn off when ingest running
|
||||
|
||||
/**
|
||||
* The options panel displayed for import, export, and CRUD operations on domain
|
||||
* categories.
|
||||
*/
|
||||
public class WebCategoriesOptionsPanel extends IngestModuleGlobalSettingsPanel implements OptionsPanel {
|
||||
|
||||
private static final Logger logger = Logger.getLogger(WebCategoriesOptionsPanel.class.getName());
|
||||
private static final String DEFAULT_EXTENSION = "json";
|
||||
private static final FileNameExtensionFilter DB_FILTER = new FileNameExtensionFilter("JSON", DEFAULT_EXTENSION);
|
||||
|
||||
private final JFileChooser fileChooser = new JFileChooser();
|
||||
private final WebCategoriesDataModel dataModel;
|
||||
private Set<String> domainCategoriesToUpper = new HashSet<>();
|
||||
|
||||
/**
|
||||
* Creates new form CustomWebCategoriesOptionsPanel
|
||||
*/
|
||||
public WebCategoriesOptionsPanel(WebCategoriesDataModel dataModel) {
|
||||
initComponents();
|
||||
this.dataModel = dataModel;
|
||||
|
||||
fileChooser.addChoosableFileFilter(DB_FILTER);
|
||||
fileChooser.setFileFilter(DB_FILTER);
|
||||
refresh();
|
||||
}
|
||||
|
||||
private DomainCategory getSelected() {
|
||||
return null;
|
||||
}
|
||||
|
||||
void refresh() {
|
||||
/
|
||||
}
|
||||
|
||||
private DomainCategory getAddEditValue(DomainCategory original) {
|
||||
JFrame parent = (this.getRootPane() != null && this.getRootPane().getParent() instanceof JFrame)
|
||||
? (JFrame) this.getRootPane().getParent()
|
||||
: null;
|
||||
|
||||
AddEditCategoryDialog addEditDialog = new AddEditCategoryDialog(parent, domainCategoriesToUpper, original);
|
||||
addEditDialog.setResizable(false);
|
||||
addEditDialog.setLocationRelativeTo(parent);
|
||||
addEditDialog.setVisible(true);
|
||||
addEditDialog.toFront();
|
||||
|
||||
if (addEditDialog.isChanged()) {
|
||||
return addEditDialog.getValue();
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This method is called from within the constructor to initialize the form.
|
||||
* WARNING: Do NOT modify this code. The content of this method is always
|
||||
* regenerated by the Form Editor.
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
// <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
|
||||
private void initComponents() {
|
||||
java.awt.GridBagConstraints gridBagConstraints;
|
||||
|
||||
javax.swing.JLabel panelDescription = new javax.swing.JLabel();
|
||||
javax.swing.JLabel categoriesTitle = new javax.swing.JLabel();
|
||||
javax.swing.JButton newEntryButton = new javax.swing.JButton();
|
||||
editEntryButton = new javax.swing.JButton();
|
||||
deleteEntryButton = new javax.swing.JButton();
|
||||
javax.swing.JButton importSetButton = new javax.swing.JButton();
|
||||
javax.swing.JButton exportSetButton = new javax.swing.JButton();
|
||||
javax.swing.JPanel bottomStrut = new javax.swing.JPanel();
|
||||
tableScrollPane = new javax.swing.JScrollPane();
|
||||
javax.swing.JPanel categoryTablePanel = categoryTable;
|
||||
|
||||
setLayout(new java.awt.GridBagLayout());
|
||||
|
||||
panelDescription.setText(org.openide.util.NbBundle.getMessage(WebCategoriesOptionsPanel.class, "WebCategoriesOptionsPanel.panelDescription.text")); // NOI18N
|
||||
panelDescription.setBorder(javax.swing.BorderFactory.createCompoundBorder(javax.swing.BorderFactory.createEtchedBorder(), javax.swing.BorderFactory.createEmptyBorder(5, 5, 5, 5)));
|
||||
gridBagConstraints = new java.awt.GridBagConstraints();
|
||||
gridBagConstraints.gridwidth = 3;
|
||||
gridBagConstraints.fill = java.awt.GridBagConstraints.VERTICAL;
|
||||
gridBagConstraints.anchor = java.awt.GridBagConstraints.LINE_START;
|
||||
gridBagConstraints.insets = new java.awt.Insets(10, 10, 10, 0);
|
||||
add(panelDescription, gridBagConstraints);
|
||||
|
||||
categoriesTitle.setText(org.openide.util.NbBundle.getMessage(WebCategoriesOptionsPanel.class, "WebCategoriesOptionsPanel.categoriesTitle.text")); // NOI18N
|
||||
gridBagConstraints = new java.awt.GridBagConstraints();
|
||||
gridBagConstraints.gridx = 0;
|
||||
gridBagConstraints.gridy = 1;
|
||||
gridBagConstraints.gridwidth = 3;
|
||||
gridBagConstraints.anchor = java.awt.GridBagConstraints.LINE_START;
|
||||
gridBagConstraints.insets = new java.awt.Insets(0, 10, 0, 0);
|
||||
add(categoriesTitle, gridBagConstraints);
|
||||
|
||||
newEntryButton.setText(org.openide.util.NbBundle.getMessage(WebCategoriesOptionsPanel.class, "WebCategoriesOptionsPanel.newEntryButton.text")); // NOI18N
|
||||
newEntryButton.addActionListener(new java.awt.event.ActionListener() {
|
||||
public void actionPerformed(java.awt.event.ActionEvent evt) {
|
||||
newEntryButtonActionPerformed(evt);
|
||||
}
|
||||
});
|
||||
gridBagConstraints = new java.awt.GridBagConstraints();
|
||||
gridBagConstraints.gridx = 0;
|
||||
gridBagConstraints.gridy = 3;
|
||||
gridBagConstraints.anchor = java.awt.GridBagConstraints.LINE_START;
|
||||
gridBagConstraints.insets = new java.awt.Insets(0, 10, 5, 5);
|
||||
add(newEntryButton, gridBagConstraints);
|
||||
|
||||
editEntryButton.setText(org.openide.util.NbBundle.getMessage(WebCategoriesOptionsPanel.class, "WebCategoriesOptionsPanel.editEntryButton.text")); // NOI18N
|
||||
editEntryButton.addActionListener(new java.awt.event.ActionListener() {
|
||||
public void actionPerformed(java.awt.event.ActionEvent evt) {
|
||||
editEntryButtonActionPerformed(evt);
|
||||
}
|
||||
});
|
||||
gridBagConstraints = new java.awt.GridBagConstraints();
|
||||
gridBagConstraints.gridx = 1;
|
||||
gridBagConstraints.gridy = 3;
|
||||
gridBagConstraints.anchor = java.awt.GridBagConstraints.LINE_START;
|
||||
gridBagConstraints.insets = new java.awt.Insets(0, 0, 5, 5);
|
||||
add(editEntryButton, gridBagConstraints);
|
||||
|
||||
deleteEntryButton.setText(org.openide.util.NbBundle.getMessage(WebCategoriesOptionsPanel.class, "WebCategoriesOptionsPanel.deleteEntryButton.text")); // NOI18N
|
||||
deleteEntryButton.addActionListener(new java.awt.event.ActionListener() {
|
||||
public void actionPerformed(java.awt.event.ActionEvent evt) {
|
||||
deleteEntryButtonActionPerformed(evt);
|
||||
}
|
||||
});
|
||||
gridBagConstraints = new java.awt.GridBagConstraints();
|
||||
gridBagConstraints.gridx = 2;
|
||||
gridBagConstraints.gridy = 3;
|
||||
gridBagConstraints.anchor = java.awt.GridBagConstraints.LINE_START;
|
||||
gridBagConstraints.insets = new java.awt.Insets(0, 0, 5, 5);
|
||||
add(deleteEntryButton, gridBagConstraints);
|
||||
|
||||
importSetButton.setText(org.openide.util.NbBundle.getMessage(WebCategoriesOptionsPanel.class, "WebCategoriesOptionsPanel.importSetButton.text")); // NOI18N
|
||||
importSetButton.addActionListener(new java.awt.event.ActionListener() {
|
||||
public void actionPerformed(java.awt.event.ActionEvent evt) {
|
||||
importSetButtonActionPerformed(evt);
|
||||
}
|
||||
});
|
||||
gridBagConstraints = new java.awt.GridBagConstraints();
|
||||
gridBagConstraints.gridx = 0;
|
||||
gridBagConstraints.gridy = 4;
|
||||
gridBagConstraints.anchor = java.awt.GridBagConstraints.LINE_START;
|
||||
gridBagConstraints.insets = new java.awt.Insets(0, 10, 5, 5);
|
||||
add(importSetButton, gridBagConstraints);
|
||||
|
||||
exportSetButton.setText(org.openide.util.NbBundle.getMessage(WebCategoriesOptionsPanel.class, "WebCategoriesOptionsPanel.exportSetButton.text")); // NOI18N
|
||||
exportSetButton.addActionListener(new java.awt.event.ActionListener() {
|
||||
public void actionPerformed(java.awt.event.ActionEvent evt) {
|
||||
exportSetButtonActionPerformed(evt);
|
||||
}
|
||||
});
|
||||
gridBagConstraints = new java.awt.GridBagConstraints();
|
||||
gridBagConstraints.gridx = 1;
|
||||
gridBagConstraints.gridy = 4;
|
||||
gridBagConstraints.anchor = java.awt.GridBagConstraints.LINE_START;
|
||||
gridBagConstraints.insets = new java.awt.Insets(0, 0, 5, 5);
|
||||
add(exportSetButton, gridBagConstraints);
|
||||
gridBagConstraints = new java.awt.GridBagConstraints();
|
||||
gridBagConstraints.gridx = 3;
|
||||
gridBagConstraints.gridy = 5;
|
||||
gridBagConstraints.fill = java.awt.GridBagConstraints.VERTICAL;
|
||||
gridBagConstraints.weightx = 1.0;
|
||||
gridBagConstraints.weighty = 1.0;
|
||||
add(bottomStrut, gridBagConstraints);
|
||||
|
||||
tableScrollPane.setMaximumSize(new java.awt.Dimension(325, 32767));
|
||||
tableScrollPane.setMinimumSize(new java.awt.Dimension(325, 300));
|
||||
tableScrollPane.setPreferredSize(new java.awt.Dimension(325, 400));
|
||||
tableScrollPane.setViewportView(categoryTablePanel);
|
||||
|
||||
gridBagConstraints = new java.awt.GridBagConstraints();
|
||||
gridBagConstraints.gridx = 0;
|
||||
gridBagConstraints.gridy = 2;
|
||||
gridBagConstraints.gridwidth = 3;
|
||||
gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST;
|
||||
gridBagConstraints.insets = new java.awt.Insets(2, 10, 5, 0);
|
||||
add(tableScrollPane, gridBagConstraints);
|
||||
}// </editor-fold>//GEN-END:initComponents
|
||||
|
||||
private void deleteEntryButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_deleteEntryButtonActionPerformed
|
||||
DomainCategory selected = getSelected();
|
||||
if (selected != null && selected.getHostSuffix() != null) {
|
||||
try {
|
||||
dataModel.deleteRecord(selected.getHostSuffix());
|
||||
refresh();
|
||||
} catch (SQLException ex) {
|
||||
logger.log(Level.WARNING, "There was an error while deleting: " + selected.getHostSuffix(), ex);
|
||||
}
|
||||
}
|
||||
}//GEN-LAST:event_deleteEntryButtonActionPerformed
|
||||
|
||||
private void newEntryButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_newEntryButtonActionPerformed
|
||||
DomainCategory newCategory = getAddEditValue(null);
|
||||
if (newCategory != null) {
|
||||
try {
|
||||
dataModel.insertUpdateSuffix(newCategory);
|
||||
refresh();
|
||||
} catch (SQLException ex) {
|
||||
logger.log(Level.WARNING, "There was an error while adding new record: " + newCategory.getHostSuffix(), ex);
|
||||
}
|
||||
}
|
||||
}//GEN-LAST:event_newEntryButtonActionPerformed
|
||||
|
||||
private void editEntryButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_editEntryButtonActionPerformed
|
||||
DomainCategory selected = getSelected();
|
||||
if (selected != null && selected.getHostSuffix() != null) {
|
||||
try {
|
||||
DomainCategory newCategory = getAddEditValue(selected);
|
||||
if (newCategory != null) {
|
||||
dataModel.insertUpdateSuffix(newCategory);
|
||||
refresh();
|
||||
}
|
||||
} catch (SQLException ex) {
|
||||
logger.log(Level.WARNING, "There was an error while editing: " + selected.getHostSuffix(), ex);
|
||||
}
|
||||
}
|
||||
}//GEN-LAST:event_editEntryButtonActionPerformed
|
||||
|
||||
@Messages({
|
||||
"WebCategoriesOptionsPanel_importSetButtonActionPerformed_errorMessage=There was an error importing this json file.",
|
||||
"WebCategoriesOptionsPanel_importSetButtonActionPerformed_errorTitle=Import Error",})
|
||||
private void importSetButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_importSetButtonActionPerformed
|
||||
int result = fileChooser.showOpenDialog(this);
|
||||
if (result == JFileChooser.APPROVE_OPTION) {
|
||||
File selectedFile = fileChooser.getSelectedFile();
|
||||
if (selectedFile != null && selectedFile.exists()) {
|
||||
try {
|
||||
dataModel.importJson(selectedFile);
|
||||
refresh();
|
||||
} catch (SQLException | IOException ex) {
|
||||
JOptionPane.showMessageDialog(
|
||||
this,
|
||||
Bundle.WebCategoriesOptionsPanel_importSetButtonActionPerformed_errorMessage(),
|
||||
Bundle.WebCategoriesOptionsPanel_importSetButtonActionPerformed_errorTitle(),
|
||||
JOptionPane.ERROR);
|
||||
logger.log(Level.WARNING, "There was an error on import.", ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
}//GEN-LAST:event_importSetButtonActionPerformed
|
||||
|
||||
@Messages({
|
||||
"WebCategoriesOptionsPanel_exportSetButtonActionPerformed_errorMessage=There was an error exporting.",
|
||||
"WebCategoriesOptionsPanel_exportSetButtonActionPerformed_errorTitle=Export Error",})
|
||||
private void exportSetButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_exportSetButtonActionPerformed
|
||||
int result = fileChooser.showSaveDialog(this);
|
||||
if (result == JFileChooser.APPROVE_OPTION) {
|
||||
File selectedFile = fileChooser.getSelectedFile();
|
||||
if (selectedFile != null && selectedFile.exists()) {
|
||||
try {
|
||||
dataModel.exportToJson(selectedFile);
|
||||
} catch (SQLException | IOException ex) {
|
||||
JOptionPane.showMessageDialog(
|
||||
this,
|
||||
Bundle.WebCategoriesOptionsPanel_importSetButtonActionPerformed_errorMessage(),
|
||||
Bundle.WebCategoriesOptionsPanel_importSetButtonActionPerformed_errorTitle(),
|
||||
JOptionPane.ERROR);
|
||||
logger.log(Level.WARNING, "There was an error on export.", ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
}//GEN-LAST:event_exportSetButtonActionPerformed
|
||||
|
||||
|
||||
// Variables declaration - do not modify//GEN-BEGIN:variables
|
||||
private javax.swing.JButton deleteEntryButton;
|
||||
private javax.swing.JButton editEntryButton;
|
||||
private javax.swing.JScrollPane tableScrollPane;
|
||||
// End of variables declaration//GEN-END:variables
|
||||
|
||||
@Override
|
||||
public void saveSettings() {
|
||||
// NO OP since saves happen whenever there is a change.
|
||||
}
|
||||
|
||||
@Override
|
||||
public void store() {
|
||||
// NO OP since saves happen whenever there is a change.
|
||||
}
|
||||
|
||||
@Override
|
||||
public void load() {
|
||||
refresh();
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user