19 package org.sleuthkit.autopsy.allcasessearch;
21 import java.awt.Color;
22 import java.awt.event.ItemEvent;
23 import java.awt.event.ItemListener;
24 import java.text.Collator;
25 import java.util.ArrayList;
26 import java.util.Collection;
27 import java.util.Collections;
28 import java.util.List;
29 import java.util.concurrent.ExecutionException;
30 import java.util.logging.Level;
31 import javax.swing.JFrame;
32 import javax.swing.SwingWorker;
33 import javax.swing.event.DocumentEvent;
34 import javax.swing.event.DocumentListener;
35 import org.apache.commons.lang3.StringUtils;
36 import org.openide.nodes.Node;
37 import org.openide.util.NbBundle.Messages;
38 import org.openide.windows.TopComponent;
39 import org.openide.windows.WindowManager;
54 "AllCasesSearchDialog.dialogTitle.text=Search Central Repository",
55 "AllCasesSearchDialog.resultsTitle.text=All Cases",
56 "AllCasesSearchDialog.resultsDescription.text=Search Central Repository",
57 "AllCasesSearchDialog.emptyNode.text=No results found.",
58 "AllCasesSearchDialog.validation.invalidHash=The supplied value is not a valid MD5 hash.",
59 "AllCasesSearchDialog.validation.invalidEmail=The supplied value is not a valid e-mail address.",
60 "AllCasesSearchDialog.validation.invalidDomain=The supplied value is not a valid domain.",
61 "AllCasesSearchDialog.validation.invalidPhone=The supplied value is not a valid phone number.",
62 "AllCasesSearchDialog.validation.invalidSsid=The supplied value is not a valid wireless network.",
63 "AllCasesSearchDialog.validation.invalidMac=The supplied value is not a valid MAC address.",
64 "AllCasesSearchDialog.validation.invalidImei=The supplied value is not a valid IMEI number.",
65 "AllCasesSearchDialog.validation.invalidImsi=The supplied value is not a valid IMSI number.",
66 "AllCasesSearchDialog.validation.invalidIccid=The supplied value is not a valid ICCID number.",
67 "AllCasesSearchDialog.validation.genericMessage=The supplied value is not valid.",
68 "# {0} - number of cases",
69 "AllCasesSearchDialog.caseLabel.text=The Central Repository contains {0} case(s)."
75 @SuppressWarnings(
"PMD.SingularField")
76 final class AllCasesSearchDialog extends javax.swing.JDialog {
78 private static final Logger logger = Logger.getLogger(AllCasesSearchDialog.class.getName());
79 private static final long serialVersionUID = 1L;
81 private final List<CorrelationAttributeInstance.Type> correlationTypes;
82 private CorrelationAttributeInstance.Type selectedCorrelationType;
83 private TextPrompt correlationValueTextFieldPrompt;
88 AllCasesSearchDialog() {
89 super((JFrame) WindowManager.getDefault().getMainWindow(), Bundle.AllCasesSearchDialog_dialogTitle_text(),
true);
90 this.correlationTypes =
new ArrayList<>();
92 customizeComponents();
101 private void search(CorrelationAttributeInstance.Type type, String[] values) {
102 new SwingWorker<List<CorrelationAttributeInstance>, Void>() {
105 protected List<CorrelationAttributeInstance> doInBackground() {
106 List<CorrelationAttributeInstance> correlationInstances =
new ArrayList<>();
108 for (String value : values) {
110 correlationInstances.addAll(CentralRepository.getInstance().getArtifactInstancesByTypeValue(type, value));
111 }
catch (CentralRepoException ex) {
112 logger.log(Level.SEVERE,
"Unable to connect to the Central Repository database.", ex);
113 }
catch (CorrelationAttributeNormalizationException ex) {
114 logger.log(Level.SEVERE,
"Unable to retrieve data from the Central Repository.", ex);
118 return correlationInstances;
122 protected void done() {
125 List<CorrelationAttributeInstance> correlationInstances = this.
get();
126 DataResultViewerTable table =
new DataResultViewerTable();
127 Collection<DataResultViewer> viewers =
new ArrayList<>(1);
130 AllCasesSearchNode searchNode =
new AllCasesSearchNode(correlationInstances);
131 TableFilterNode tableFilterNode =
new TableFilterNode(searchNode,
true, searchNode.getName());
133 String resultsText = String.format(
"%s (%s)",
134 Bundle.AllCasesSearchDialog_resultsTitle_text(), type.getDisplayName());
135 final TopComponent searchResultWin;
136 if (correlationInstances.isEmpty()) {
137 Node emptyNode =
new TableFilterNode(
138 new EmptyNode(Bundle.AllCasesSearchDialog_emptyNode_text()),
true);
139 searchResultWin = DataResultTopComponent.createInstance(
140 resultsText, Bundle.AllCasesSearchDialog_resultsDescription_text(), emptyNode, 0);
142 searchResultWin = DataResultTopComponent.createInstance(
143 resultsText, Bundle.AllCasesSearchDialog_resultsDescription_text(), tableFilterNode, correlationInstances.size(), viewers);
145 searchResultWin.requestActive();
146 }
catch (ExecutionException | InterruptedException ex) {
147 logger.log(Level.SEVERE,
"Unable to get CorrelationAttributeInstances.", ex);
158 @SuppressWarnings(
"unchecked")
160 private
void initComponents() {
162 correlationValueLabel =
new javax.swing.JLabel();
163 searchButton =
new javax.swing.JButton();
164 correlationTypeComboBox =
new javax.swing.JComboBox<>();
165 correlationTypeLabel =
new javax.swing.JLabel();
166 errorLabel =
new javax.swing.JLabel();
167 descriptionLabel =
new javax.swing.JLabel();
168 casesLabel =
new javax.swing.JLabel();
169 correlationValueScrollPane =
new javax.swing.JScrollPane();
170 correlationValueTextArea =
new javax.swing.JTextArea();
171 normalizedLabel =
new javax.swing.JLabel();
173 setDefaultCloseOperation(javax.swing.WindowConstants.DISPOSE_ON_CLOSE);
176 org.openide.awt.Mnemonics.setLocalizedText(correlationValueLabel,
org.openide.util.NbBundle.getMessage(AllCasesSearchDialog.class,
"AllCasesSearchDialog.correlationValueLabel.text"));
178 org.openide.awt.Mnemonics.setLocalizedText(searchButton,
org.openide.util.NbBundle.getMessage(AllCasesSearchDialog.class,
"AllCasesSearchDialog.searchButton.text"));
179 searchButton.addActionListener(
new java.awt.event.ActionListener() {
180 public void actionPerformed(java.awt.event.ActionEvent evt) {
181 searchButtonActionPerformed(evt);
185 correlationTypeComboBox.addActionListener(
new java.awt.event.ActionListener() {
186 public void actionPerformed(java.awt.event.ActionEvent evt) {
187 correlationTypeComboBoxActionPerformed(evt);
191 org.openide.awt.Mnemonics.setLocalizedText(correlationTypeLabel,
org.openide.util.NbBundle.getMessage(AllCasesSearchDialog.class,
"AllCasesSearchDialog.correlationTypeLabel.text"));
193 errorLabel.setForeground(
new java.awt.Color(255, 0, 0));
194 org.openide.awt.Mnemonics.setLocalizedText(errorLabel,
org.openide.util.NbBundle.getMessage(AllCasesSearchDialog.class,
"AllCasesSearchDialog.errorLabel.text"));
196 org.openide.awt.Mnemonics.setLocalizedText(descriptionLabel,
org.openide.util.NbBundle.getMessage(AllCasesSearchDialog.class,
"AllCasesSearchDialog.descriptionLabel.text"));
198 casesLabel.setHorizontalAlignment(javax.swing.SwingConstants.LEFT);
199 org.openide.awt.Mnemonics.setLocalizedText(casesLabel,
org.openide.util.NbBundle.getMessage(AllCasesSearchDialog.class,
"AllCasesSearchDialog.casesLabel.text"));
201 correlationValueTextArea.setColumns(20);
202 correlationValueTextArea.setRows(5);
203 correlationValueTextArea.setText(
org.openide.util.NbBundle.getMessage(AllCasesSearchDialog.class,
"AllCasesSearchDialog.correlationValueTextArea.text"));
204 correlationValueScrollPane.setViewportView(correlationValueTextArea);
206 org.openide.awt.Mnemonics.setLocalizedText(normalizedLabel,
org.openide.util.NbBundle.getMessage(AllCasesSearchDialog.class,
"AllCasesSearchDialog.normalizedLabel.text"));
208 javax.swing.GroupLayout layout =
new javax.swing.GroupLayout(getContentPane());
209 getContentPane().setLayout(layout);
210 layout.setHorizontalGroup(
211 layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
212 .addGroup(layout.createSequentialGroup()
214 .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
215 .addComponent(descriptionLabel)
216 .addGroup(layout.createSequentialGroup()
217 .addComponent(casesLabel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
218 .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
219 .addComponent(searchButton))
220 .addGroup(layout.createSequentialGroup()
221 .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
222 .addComponent(correlationValueLabel)
223 .addComponent(correlationTypeLabel))
224 .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
225 .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
226 .addGroup(layout.createSequentialGroup()
227 .addComponent(normalizedLabel)
228 .addGap(0, 0, Short.MAX_VALUE))
229 .addGroup(layout.createSequentialGroup()
230 .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
231 .addComponent(correlationTypeComboBox, 0, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
232 .addGroup(layout.createSequentialGroup()
233 .addComponent(correlationValueScrollPane, javax.swing.GroupLayout.PREFERRED_SIZE, 379, javax.swing.GroupLayout.PREFERRED_SIZE)
234 .addGap(0, 0, Short.MAX_VALUE)))
235 .addGap(142, 142, 142))
236 .addComponent(errorLabel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))))
239 layout.setVerticalGroup(
240 layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
241 .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
243 .addComponent(descriptionLabel, javax.swing.GroupLayout.PREFERRED_SIZE, 39, javax.swing.GroupLayout.PREFERRED_SIZE)
245 .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
246 .addComponent(correlationTypeComboBox, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
247 .addComponent(correlationTypeLabel))
249 .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
250 .addComponent(correlationValueLabel)
251 .addComponent(correlationValueScrollPane, javax.swing.GroupLayout.PREFERRED_SIZE, 190, javax.swing.GroupLayout.PREFERRED_SIZE))
252 .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
253 .addComponent(normalizedLabel)
254 .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, 19, Short.MAX_VALUE)
255 .addComponent(errorLabel)
256 .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
257 .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
258 .addComponent(casesLabel, javax.swing.GroupLayout.Alignment.TRAILING)
259 .addComponent(searchButton, javax.swing.GroupLayout.Alignment.TRAILING))
263 searchButton.getAccessibleContext().setAccessibleName(
org.openide.util.NbBundle.getMessage(AllCasesSearchDialog.class,
"AllCasesSearchDialog.searchButton.AccessibleContext.accessibleName"));
264 searchButton.getAccessibleContext().setAccessibleDescription(
org.openide.util.NbBundle.getMessage(AllCasesSearchDialog.class,
"AllCasesSearchDialog.searchButton.AccessibleContext.accessibleDescription"));
269 private void searchButtonActionPerformed(java.awt.event.ActionEvent evt) {
270 CorrelationAttributeInstance.Type correlationType = selectedCorrelationType;
271 String correlationValue = correlationValueTextArea.getText().trim();
273 String[] correlationValueLines = correlationValue.split(
"\r\n|\n|\r");
276 if (validateInputs(correlationType, correlationValueLines)) {
277 search(correlationType, correlationValueLines);
280 String validationMessage;
281 switch (correlationType.getId()) {
282 case CorrelationAttributeInstance.FILES_TYPE_ID:
283 validationMessage = Bundle.AllCasesSearchDialog_validation_invalidHash();
285 case CorrelationAttributeInstance.DOMAIN_TYPE_ID:
286 validationMessage = Bundle.AllCasesSearchDialog_validation_invalidDomain();
288 case CorrelationAttributeInstance.EMAIL_TYPE_ID:
289 validationMessage = Bundle.AllCasesSearchDialog_validation_invalidEmail();
291 case CorrelationAttributeInstance.PHONE_TYPE_ID:
292 validationMessage = Bundle.AllCasesSearchDialog_validation_invalidPhone();
294 case CorrelationAttributeInstance.SSID_TYPE_ID:
295 validationMessage = Bundle.AllCasesSearchDialog_validation_invalidSsid();
297 case CorrelationAttributeInstance.MAC_TYPE_ID:
298 validationMessage = Bundle.AllCasesSearchDialog_validation_invalidMac();
300 case CorrelationAttributeInstance.IMEI_TYPE_ID:
301 validationMessage = Bundle.AllCasesSearchDialog_validation_invalidImei();
303 case CorrelationAttributeInstance.IMSI_TYPE_ID:
304 validationMessage = Bundle.AllCasesSearchDialog_validation_invalidImsi();
306 case CorrelationAttributeInstance.ICCID_TYPE_ID:
307 validationMessage = Bundle.AllCasesSearchDialog_validation_invalidIccid();
310 validationMessage = Bundle.AllCasesSearchDialog_validation_genericMessage();
315 errorLabel.setText(validationMessage);
316 searchButton.setEnabled(
false);
317 correlationValueTextArea.grabFocus();
322 private void correlationTypeComboBoxActionPerformed(java.awt.event.ActionEvent evt) {
324 errorLabel.setText(
"");
335 private boolean validateInputs(CorrelationAttributeInstance.Type type, String[] values) {
337 for (String value : values) {
338 CorrelationAttributeNormalizer.normalize(type, value);
340 }
catch (CorrelationAttributeNormalizationException ex) {
351 private void customizeComponents() {
352 searchButton.setEnabled(
false);
358 CentralRepository dbManager = CentralRepository.getInstance();
359 correlationTypes.clear();
360 correlationTypes.addAll(dbManager.getDefinedCorrelationTypes());
362 int numberOfCases = dbManager.getCases().size();
363 casesLabel.setText(Bundle.AllCasesSearchDialog_caseLabel_text(numberOfCases));
364 }
catch (CentralRepoException ex) {
365 logger.log(Level.SEVERE,
"Unable to connect to the Central Repository database.", ex);
368 List<String> displayNames =
new ArrayList<>();
369 for (CorrelationAttributeInstance.Type type : correlationTypes) {
370 String displayName = type.getDisplayName();
371 if (displayName.toLowerCase().contains(
"addresses")) {
372 type.setDisplayName(displayName.replace(
"Addresses",
"Address"));
373 }
else if (displayName.toLowerCase().equals(
"files")) {
374 type.setDisplayName(
"File MD5");
375 }
else if (displayName.toLowerCase().endsWith(
"s") && !displayName.toLowerCase().endsWith(
"address")) {
376 type.setDisplayName(StringUtils.substring(displayName, 0, displayName.length() - 1));
378 type.setDisplayName(displayName);
381 displayNames.add(type.getDisplayName());
383 Collections.sort(displayNames);
384 for (String displayName : displayNames) {
385 correlationTypeComboBox.addItem(displayName);
388 correlationTypeComboBox.setSelectedIndex(0);
390 correlationTypeComboBox.addItemListener(
new ItemListener() {
392 public void itemStateChanged(ItemEvent e) {
393 updateSelectedType();
394 updateCorrelationValueTextFieldPrompt();
395 updateSearchButton();
399 updateSelectedType();
404 correlationValueTextArea.getDocument().addDocumentListener(
new DocumentListener() {
406 public void changedUpdate(DocumentEvent e) {
407 updateSearchButton();
411 public void insertUpdate(DocumentEvent e) {
412 updateSearchButton();
416 public void removeUpdate(DocumentEvent e) {
417 updateSearchButton();
421 updateCorrelationValueTextFieldPrompt();
425 "AllCasesSearchDialog.correlationValueTextField.filesExample=Example: \"f0e1d2c3b4a5968778695a4b3c2d1e0f\"",
426 "AllCasesSearchDialog.correlationValueTextField.domainExample=Example: \"domain.com\"",
427 "AllCasesSearchDialog.correlationValueTextField.emailExample=Example: \"user@host.com\"",
428 "AllCasesSearchDialog.correlationValueTextField.phoneExample=Example: \"(800)123-4567\"",
429 "AllCasesSearchDialog.correlationValueTextField.usbExample=Example: \"4&1234567&0\"",
430 "AllCasesSearchDialog.correlationValueTextField.ssidExample=Example: \"WirelessNetwork-5G\"",
431 "AllCasesSearchDialog.correlationValueTextField.macExample=Example: \"0C-14-F2-01-AF-45\"",
432 "AllCasesSearchDialog.correlationValueTextField.imeiExample=Example: \"351756061523999\"",
433 "AllCasesSearchDialog.correlationValueTextField.imsiExample=Example: \"310150123456789\"",
434 "AllCasesSearchDialog.correlationValueTextField.iccidExample=Example: \"89 91 19 1299 99 329451 0\""
440 private void updateCorrelationValueTextFieldPrompt() {
445 switch (selectedCorrelationType.getId()) {
446 case CorrelationAttributeInstance.FILES_TYPE_ID:
447 text = Bundle.AllCasesSearchDialog_correlationValueTextField_filesExample();
449 case CorrelationAttributeInstance.DOMAIN_TYPE_ID:
450 text = Bundle.AllCasesSearchDialog_correlationValueTextField_domainExample();
452 case CorrelationAttributeInstance.EMAIL_TYPE_ID:
453 text = Bundle.AllCasesSearchDialog_correlationValueTextField_emailExample();
455 case CorrelationAttributeInstance.PHONE_TYPE_ID:
456 text = Bundle.AllCasesSearchDialog_correlationValueTextField_phoneExample();
458 case CorrelationAttributeInstance.USBID_TYPE_ID:
459 text = Bundle.AllCasesSearchDialog_correlationValueTextField_usbExample();
461 case CorrelationAttributeInstance.SSID_TYPE_ID:
462 text = Bundle.AllCasesSearchDialog_correlationValueTextField_ssidExample();
464 case CorrelationAttributeInstance.MAC_TYPE_ID:
465 text = Bundle.AllCasesSearchDialog_correlationValueTextField_macExample();
467 case CorrelationAttributeInstance.IMEI_TYPE_ID:
468 text = Bundle.AllCasesSearchDialog_correlationValueTextField_imeiExample();
470 case CorrelationAttributeInstance.IMSI_TYPE_ID:
471 text = Bundle.AllCasesSearchDialog_correlationValueTextField_imsiExample();
473 case CorrelationAttributeInstance.ICCID_TYPE_ID:
474 text = Bundle.AllCasesSearchDialog_correlationValueTextField_iccidExample();
480 correlationValueTextFieldPrompt =
new TextPrompt(text, correlationValueTextArea);
485 correlationValueTextFieldPrompt.setForeground(Color.LIGHT_GRAY);
486 correlationValueTextFieldPrompt.changeAlpha(0.9f);
496 private void updateSelectedType() {
497 for (CorrelationAttributeInstance.Type type : correlationTypes) {
498 if (type.getDisplayName().equals((String) correlationTypeComboBox.getSelectedItem())) {
499 selectedCorrelationType = type;
509 private void updateSearchButton() {
510 searchButton.setEnabled(correlationValueTextArea.getText().isEmpty() ==
false);
516 public void display() {
517 this.setLocationRelativeTo(WindowManager.getDefault().getMainWindow());
522 private javax.swing.JLabel casesLabel;
523 private javax.swing.JComboBox<String> correlationTypeComboBox;
524 private javax.swing.JLabel correlationTypeLabel;
525 private javax.swing.JLabel correlationValueLabel;
526 private javax.swing.JScrollPane correlationValueScrollPane;
527 private javax.swing.JTextArea correlationValueTextArea;
528 private javax.swing.JLabel descriptionLabel;
529 private javax.swing.JLabel errorLabel;
530 private javax.swing.JLabel normalizedLabel;
531 private javax.swing.JButton searchButton;