Autopsy  4.7.0
Graphical digital forensics platform for The Sleuth Kit and other tools.
FilesSetRulePanel.java
Go to the documentation of this file.
1 /*
2  * Autopsy Forensic Browser
3  *
4  * Copyright 2014-2018 Basis Technology Corp.
5  * Contact: carrier <at> sleuthkit <dot> org
6  *
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  *
11  * http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  */
19 package org.sleuthkit.autopsy.modules.interestingitems;
20 
21 import java.awt.event.ActionEvent;
22 import java.util.List;
23 import java.util.SortedSet;
24 import java.util.logging.Level;
25 import java.util.regex.Pattern;
26 import java.util.regex.PatternSyntaxException;
27 import javax.swing.JButton;
28 import javax.swing.JComponent;
29 import javax.swing.JOptionPane;
30 import org.openide.DialogDisplayer;
31 import org.openide.NotifyDescriptor;
32 import org.openide.util.NbBundle;
33 import org.openide.util.NbBundle.Messages;
37 
41 @SuppressWarnings("PMD.SingularField") // UI widgets cause lots of false positives
42 final class FilesSetRulePanel extends javax.swing.JPanel {
43 
44  @Messages({
45  "FilesSetRulePanel.bytes=Bytes",
46  "FilesSetRulePanel.kiloBytes=Kilobytes",
47  "FilesSetRulePanel.megaBytes=Megabytes",
48  "FilesSetRulePanel.gigaBytes=Gigabytes",
49  "FilesSetRulePanel.NoConditionError=Must have at least one condition to make a rule.",
50  "FilesSetRulePanel.NoMimeTypeError=Please select a valid MIME type.",
51  "FilesSetRulePanel.NoNameError=Name cannot be empty",
52  "FilesSetRulePanel.NoPathError=Path cannot be empty",
53  "FilesSetRulePanel.DaysIncludedEmptyError=Number of days included cannot be empty.",
54  "FilesSetRulePanel.DaysIncludedInvalidError=Number of days included must be a positive integer.",
55  "FilesSetRulePanel.ZeroFileSizeError=File size condition value must not be 0 (Unless = is selected)."
56  })
57 
58  private static final long serialVersionUID = 1L;
59  private static final Logger logger = Logger.getLogger(FilesSetRulePanel.class.getName());
60  private static final String SLEUTHKIT_PATH_SEPARATOR = "/"; // NON-NLS
61  private static final List<String> ILLEGAL_FILE_NAME_CHARS = FilesSetsManager.getIllegalFileNameChars();
62  private static final List<String> ILLEGAL_FILE_PATH_CHARS = FilesSetsManager.getIllegalFilePathChars();
63  private JButton okButton;
64  private JButton cancelButton;
65 
69  FilesSetRulePanel(JButton okButton, JButton cancelButton, PANEL_TYPE panelType) {
70  initComponents();
71  if (panelType == FilesSetDefsPanel.PANEL_TYPE.FILE_INGEST_FILTERS) { //Hide the mimetype settings when this is displaying a FileSet rule instead of a interesting item rule
72  mimeTypeComboBox.setVisible(false);
73  mimeCheck.setVisible(false);
74  fileSizeComboBox.setVisible(false);
75  fileSizeCheck.setVisible(false);
76  equalitySymbolComboBox.setVisible(false);
77  fileSizeSpinner.setVisible(false);
78  jLabel1.setVisible(false);
79  filesRadioButton.setVisible(false);
80  dirsRadioButton.setVisible(false);
81  allRadioButton.setVisible(false);
82  org.openide.awt.Mnemonics.setLocalizedText(jLabel5, org.openide.util.NbBundle.getMessage(FilesSetRulePanel.class, "FilesSetRulePanel.ingest.jLabel5.text")); // NOI18N
83 
84  } else {
85  populateMimeTypesComboBox();
86  }
87  this.dateCheckActionPerformed(null);
88  populateComponentsWithDefaultValues();
89  this.setButtons(okButton, cancelButton);
90  }
91 
97  FilesSetRulePanel(FilesSet.Rule rule, JButton okButton, JButton cancelButton, PANEL_TYPE panelType) {
98  initComponents();
99  if (panelType == FilesSetDefsPanel.PANEL_TYPE.FILE_INGEST_FILTERS) { //Hide the mimetype settings when this is displaying a FileSet rule instead of a interesting item rule
100  mimeTypeComboBox.setVisible(false);
101  mimeCheck.setVisible(false);
102  fileSizeComboBox.setVisible(false);
103  fileSizeCheck.setVisible(false);
104  equalitySymbolComboBox.setVisible(false);
105  fileSizeSpinner.setVisible(false);
106  jLabel1.setVisible(false);
107  filesRadioButton.setVisible(false);
108  dirsRadioButton.setVisible(false);
109  allRadioButton.setVisible(false);
110  } else {
111  populateMimeTypesComboBox();
112  populateMimeConditionComponents(rule);
113  populateSizeConditionComponents(rule);
114 
115  }
116  populateMimeTypesComboBox();
117  populateRuleNameComponent(rule);
118  populateTypeConditionComponents(rule);
119  populateNameConditionComponents(rule);
120  populatePathConditionComponents(rule);
121  populateDateConditionComponents(rule);
122  this.setButtons(okButton, cancelButton);
123  }
124 
128  private void populateComponentsWithDefaultValues() {
129  this.filesRadioButton.setSelected(true);
130  this.fullNameRadioButton.setSelected(true);
131  this.equalitySymbolComboBox.setSelectedItem(FilesSet.Rule.FileSizeCondition.COMPARATOR.GREATER_THAN_EQUAL.getSymbol());
132  this.fileSizeComboBox.setSelectedItem(FilesSet.Rule.FileSizeCondition.SIZE_UNIT.KILOBYTE.getName());
133  this.mimeTypeComboBox.setSelectedIndex(0);
134  }
135 
136  private void populateMimeTypesComboBox() {
137  try {
138  SortedSet<String> detectableMimeTypes = FileTypeDetector.getDetectedTypes();
139  detectableMimeTypes.forEach((type) -> {
140  mimeTypeComboBox.addItem(type);
141  });
142  } catch (FileTypeDetector.FileTypeDetectorInitException ex) {
143  logger.log(Level.SEVERE, "Unable to get detectable file types", ex);
144  }
145  this.setOkButton();
146  }
147 
153  private void populateRuleNameComponent(FilesSet.Rule rule) {
154  this.ruleNameTextField.setText(rule.getName());
155  }
156 
157  private void populateMimeConditionComponents(FilesSet.Rule rule) {
158  FilesSet.Rule.MimeTypeCondition mimeTypeCondition = rule.getMimeTypeCondition();
159  if (mimeTypeCondition != null) {
160  this.mimeCheck.setSelected(true);
161  this.mimeCheckActionPerformed(null);
162  this.mimeTypeComboBox.setSelectedItem(mimeTypeCondition.getMimeType());
163  }
164  }
165 
166  private void populateSizeConditionComponents(FilesSet.Rule rule) {
167  FilesSet.Rule.FileSizeCondition fileSizeCondition = rule.getFileSizeCondition();
168  if (fileSizeCondition != null) {
169  this.fileSizeCheck.setSelected(true);
170  this.fileSizeCheckActionPerformed(null);
171  this.fileSizeSpinner.setValue(fileSizeCondition.getSizeValue());
172  this.fileSizeComboBox.setSelectedItem(fileSizeCondition.getUnit().getName());
173  this.equalitySymbolComboBox.setSelectedItem(fileSizeCondition.getComparator().getSymbol());
174  }
175  }
176 
181  private void setOkButton() {
182  if (this.okButton != null) {
183  this.okButton.setEnabled(this.fileSizeCheck.isSelected() || this.mimeCheck.isSelected()
184  || this.nameCheck.isSelected() || this.pathCheck.isSelected() || this.dateCheck.isSelected());
185  }
186  }
187 
195  private JOptionPane getOptionPane(JComponent parent) {
196  JOptionPane pane;
197  if (!(parent instanceof JOptionPane)) {
198  pane = getOptionPane((JComponent) parent.getParent());
199  } else {
200  pane = (JOptionPane) parent;
201  }
202  return pane;
203  }
204 
211  private void setButtons(JButton ok, JButton cancel) {
212  this.okButton = ok;
213  this.cancelButton = cancel;
214  okButton.addActionListener((ActionEvent e) -> {
215  JOptionPane pane = getOptionPane(okButton);
216  pane.setValue(okButton);
217  });
218  cancelButton.addActionListener((ActionEvent e) -> {
219  JOptionPane pane = getOptionPane(cancelButton);
220  pane.setValue(cancelButton);
221  });
222  this.setOkButton();
223  }
224 
231  private void populateTypeConditionComponents(FilesSet.Rule rule) {
232  FilesSet.Rule.MetaTypeCondition typeCondition = rule.getMetaTypeCondition();
233  switch (typeCondition.getMetaType()) {
234  case FILES:
235  this.filesRadioButton.setSelected(true);
236  break;
237  case DIRECTORIES:
238  this.dirsRadioButton.setSelected(true);
239  break;
240  case ALL:
241  this.allRadioButton.setSelected(true);
242  break;
243  }
244  }
245 
251  private void populateNameConditionComponents(FilesSet.Rule rule) {
252  FilesSet.Rule.FileNameCondition nameCondition = rule.getFileNameCondition();
253  if (nameCondition != null) {
254  this.nameCheck.setSelected(true);
255  this.nameCheckActionPerformed(null);
256  this.nameTextField.setText(nameCondition.getTextToMatch());
257  this.nameRegexCheckbox.setSelected(nameCondition.isRegex());
258  if (nameCondition instanceof FilesSet.Rule.FullNameCondition) {
259  this.fullNameRadioButton.setSelected(true);
260  } else {
261  this.extensionRadioButton.setSelected(true);
262  }
263  }
264  }
265 
272  private void populatePathConditionComponents(FilesSet.Rule rule) {
273  FilesSet.Rule.ParentPathCondition pathCondition = rule.getPathCondition();
274  if (pathCondition != null) {
275  this.pathCheck.setSelected(true);
276  this.pathCheckActionPerformed(null);
277  this.pathTextField.setText(pathCondition.getTextToMatch());
278  this.pathRegexCheckBox.setSelected(pathCondition.isRegex());
279  }
280  }
281 
288  private void populateDateConditionComponents(FilesSet.Rule rule) {
289  FilesSet.Rule.DateCondition dateCondition = rule.getDateCondition();
290  if (dateCondition != null) {
291  this.dateCheck.setSelected(true);
292  this.dateCheckActionPerformed(null);
293  this.daysIncludedTextField.setText(Integer.toString(dateCondition.getDaysIncluded()));
294  }
295  }
296 
304  boolean isValidRuleDefinition() {
305 
306  if (!(this.mimeCheck.isSelected() || this.fileSizeCheck.isSelected() || this.pathCheck.isSelected() || this.nameCheck.isSelected() || this.dateCheck.isSelected())) {
307  NotifyDescriptor notifyDesc = new NotifyDescriptor.Message(
308  Bundle.FilesSetRulePanel_NoConditionError(),
309  NotifyDescriptor.WARNING_MESSAGE);
310  DialogDisplayer.getDefault().notify(notifyDesc);
311  return false;
312  }
313 
314  if (this.nameCheck.isSelected()) {
315  // The name condition must either be a regular expression that compiles or
316  // a string without illegal file name chars.
317  if (this.nameTextField.getText().isEmpty()) {
318  NotifyDescriptor notifyDesc = new NotifyDescriptor.Message(
319  Bundle.FilesSetRulePanel_NoNameError(),
320  NotifyDescriptor.WARNING_MESSAGE);
321  DialogDisplayer.getDefault().notify(notifyDesc);
322  return false;
323  }
324  if (this.nameRegexCheckbox.isSelected()) {
325  try {
326  Pattern.compile(this.nameTextField.getText());
327  } catch (PatternSyntaxException ex) {
328  NotifyDescriptor notifyDesc = new NotifyDescriptor.Message(
329  NbBundle.getMessage(FilesSetPanel.class, "FilesSetRulePanel.messages.invalidNameRegex", ex.getLocalizedMessage()),
330  NotifyDescriptor.WARNING_MESSAGE);
331  DialogDisplayer.getDefault().notify(notifyDesc);
332  return false;
333  }
334  } else if (this.nameTextField.getText().isEmpty() || !FilesSetRulePanel.containsOnlyLegalChars(this.nameTextField.getText(), FilesSetRulePanel.ILLEGAL_FILE_NAME_CHARS)) {
335  NotifyDescriptor notifyDesc = new NotifyDescriptor.Message(
336  NbBundle.getMessage(FilesSetPanel.class, "FilesSetRulePanel.messages.invalidCharInName"),
337  NotifyDescriptor.WARNING_MESSAGE);
338  DialogDisplayer.getDefault().notify(notifyDesc);
339  return false;
340  }
341  }
342 
343  // The path condition, if specified, must either be a regular expression
344  // that compiles or a string without illegal file path chars.
345  if (this.pathCheck.isSelected()) {
346  if (this.pathTextField.getText().isEmpty()) {
347  NotifyDescriptor notifyDesc = new NotifyDescriptor.Message(
348  Bundle.FilesSetRulePanel_NoPathError(),
349  NotifyDescriptor.WARNING_MESSAGE);
350  DialogDisplayer.getDefault().notify(notifyDesc);
351  return false;
352  }
353  if (this.pathRegexCheckBox.isSelected()) {
354  try {
355  Pattern.compile(this.pathTextField.getText());
356  } catch (PatternSyntaxException ex) {
357  NotifyDescriptor notifyDesc = new NotifyDescriptor.Message(
358  NbBundle.getMessage(FilesSetPanel.class, "FilesSetRulePanel.messages.invalidPathRegex", ex.getLocalizedMessage()),
359  NotifyDescriptor.WARNING_MESSAGE);
360  DialogDisplayer.getDefault().notify(notifyDesc);
361  return false;
362  }
363  } else if (this.pathTextField.getText().isEmpty() || !FilesSetRulePanel.containsOnlyLegalChars(this.pathTextField.getText(), FilesSetRulePanel.ILLEGAL_FILE_PATH_CHARS)) {
364  NotifyDescriptor notifyDesc = new NotifyDescriptor.Message(
365  NbBundle.getMessage(FilesSetPanel.class, "FilesSetRulePanel.messages.invalidCharInPath"),
366  NotifyDescriptor.WARNING_MESSAGE);
367  DialogDisplayer.getDefault().notify(notifyDesc);
368  return false;
369  }
370  }
371  if (this.mimeCheck.isSelected()) {
372  if (this.mimeTypeComboBox.getSelectedIndex() == 0) {
373  NotifyDescriptor notifyDesc = new NotifyDescriptor.Message(
374  Bundle.FilesSetRulePanel_NoMimeTypeError(),
375  NotifyDescriptor.WARNING_MESSAGE);
376  DialogDisplayer.getDefault().notify(notifyDesc);
377  return false;
378  }
379  }
380  if (this.fileSizeCheck.isSelected()) {
381  if ((Integer) this.fileSizeSpinner.getValue() == 0 && !((String) this.equalitySymbolComboBox.getSelectedItem()).equals("=")) {
382  NotifyDescriptor notifyDesc = new NotifyDescriptor.Message(
383  Bundle.FilesSetRulePanel_ZeroFileSizeError(),
384  NotifyDescriptor.WARNING_MESSAGE);
385  DialogDisplayer.getDefault().notify(notifyDesc);
386  return false;
387  }
388  }
389 
390  if (this.dateCheck.isSelected()) {
391  if (this.daysIncludedTextField.getText().isEmpty()) {
392  NotifyDescriptor notifyDesc = new NotifyDescriptor.Message(
393  Bundle.FilesSetRulePanel_DaysIncludedEmptyError(),
394  NotifyDescriptor.WARNING_MESSAGE);
395  DialogDisplayer.getDefault().notify(notifyDesc);
396  return false;
397  }
398  try {
399  int value = Integer.parseInt(daysIncludedTextField.getText());
400  if (value < 0) {
401  throw new NumberFormatException("Negative numbers are not allowed for the within N days condition");
402  }
403  } catch (NumberFormatException e) {
404  //field did not contain an integer
405  NotifyDescriptor notifyDesc = new NotifyDescriptor.Message(
406  Bundle.FilesSetRulePanel_DaysIncludedInvalidError(),
407  NotifyDescriptor.WARNING_MESSAGE);
408  DialogDisplayer.getDefault().notify(notifyDesc);
409  return false;
410  }
411  }
412  return true;
413  }
414 
420  String getRuleName() {
421  return this.ruleNameTextField.getText();
422  }
423 
433  FilesSet.Rule.FileNameCondition getFileNameCondition() throws IllegalStateException {
434  FilesSet.Rule.FileNameCondition condition = null;
435  if (!this.nameTextField.getText().isEmpty()) {
436  if (this.nameRegexCheckbox.isSelected()) {
437  try {
438  Pattern pattern = Pattern.compile(this.nameTextField.getText());
439  if (this.fullNameRadioButton.isSelected()) {
440  condition = new FilesSet.Rule.FullNameCondition(pattern);
441  } else {
442  condition = new FilesSet.Rule.ExtensionCondition(pattern);
443  }
444  } catch (PatternSyntaxException ex) {
445  logger.log(Level.SEVERE, "Attempt to get regex name condition that does not compile", ex); // NON-NLS
446  throw new IllegalStateException("The files set rule panel name condition is not in a valid state"); // NON-NLS
447  }
448  } else if (FilesSetRulePanel.containsOnlyLegalChars(this.nameTextField.getText(), FilesSetRulePanel.ILLEGAL_FILE_NAME_CHARS)) {
449  if (this.fullNameRadioButton.isSelected()) {
450  condition = new FilesSet.Rule.FullNameCondition(this.nameTextField.getText());
451  } else {
452  condition = new FilesSet.Rule.ExtensionCondition(this.nameTextField.getText());
453  }
454  } else {
455  logger.log(Level.SEVERE, "Attempt to get name condition with illegal chars"); // NON-NLS
456  throw new IllegalStateException("The files set rule panel name condition is not in a valid state"); // NON-NLS
457  }
458  }
459  return condition;
460  }
461 
467  FilesSet.Rule.MimeTypeCondition getMimeTypeCondition() {
468  FilesSet.Rule.MimeTypeCondition condition = null;
469  if (!this.mimeTypeComboBox.getSelectedItem().equals("")) {
470  condition = new FilesSet.Rule.MimeTypeCondition((String) this.mimeTypeComboBox.getSelectedItem());
471  }
472  return condition;
473  }
474 
480  FilesSet.Rule.FileSizeCondition getFileSizeCondition() {
481  FilesSet.Rule.FileSizeCondition condition = null;
482  if (this.fileSizeCheck.isSelected()) {
483  if ((Integer) this.fileSizeSpinner.getValue() != 0 || ((String) this.equalitySymbolComboBox.getSelectedItem()).equals("=")) {
484  FilesSet.Rule.FileSizeCondition.COMPARATOR comparator = FilesSet.Rule.FileSizeCondition.COMPARATOR.fromSymbol((String) this.equalitySymbolComboBox.getSelectedItem());
485  FilesSet.Rule.FileSizeCondition.SIZE_UNIT unit = FilesSet.Rule.FileSizeCondition.SIZE_UNIT.fromName((String) this.fileSizeComboBox.getSelectedItem());
486  int fileSizeValue = (Integer) this.fileSizeSpinner.getValue();
487  condition = new FilesSet.Rule.FileSizeCondition(comparator, unit, fileSizeValue);
488  }
489  }
490  return condition;
491  }
492 
499  FilesSet.Rule.MetaTypeCondition getMetaTypeCondition() {
500  if (this.filesRadioButton.isSelected()) {
501  return new FilesSet.Rule.MetaTypeCondition(FilesSet.Rule.MetaTypeCondition.Type.FILES);
502  } else if (this.dirsRadioButton.isSelected()) {
503  return new FilesSet.Rule.MetaTypeCondition(FilesSet.Rule.MetaTypeCondition.Type.DIRECTORIES);
504  } else {
505  return new FilesSet.Rule.MetaTypeCondition(FilesSet.Rule.MetaTypeCondition.Type.ALL);
506  }
507  }
508 
518  FilesSet.Rule.ParentPathCondition getPathCondition() throws IllegalStateException {
519  FilesSet.Rule.ParentPathCondition condition = null;
520  if (!this.pathTextField.getText().isEmpty()) {
521  if (this.pathRegexCheckBox.isSelected()) {
522  try {
523  condition = new FilesSet.Rule.ParentPathCondition(Pattern.compile(this.pathTextField.getText()));
524  } catch (PatternSyntaxException ex) {
525  logger.log(Level.SEVERE, "Attempt to get malformed path condition", ex); // NON-NLS
526  throw new IllegalStateException("The files set rule panel path condition is not in a valid state"); // NON-NLS
527  }
528  } else {
529  String path = this.pathTextField.getText();
530  if (FilesSetRulePanel.containsOnlyLegalChars(path, FilesSetRulePanel.ILLEGAL_FILE_PATH_CHARS)) {
531  // Add a leading path separator if omitted.
532  if (!path.startsWith(FilesSetRulePanel.SLEUTHKIT_PATH_SEPARATOR)) {
533  path = FilesSetRulePanel.SLEUTHKIT_PATH_SEPARATOR + path;
534  }
535  // Add a trailing path separator if omitted.
536  if (!path.endsWith(FilesSetRulePanel.SLEUTHKIT_PATH_SEPARATOR)) {
537  path += FilesSetRulePanel.SLEUTHKIT_PATH_SEPARATOR;
538  }
539  condition = new FilesSet.Rule.ParentPathCondition(path);
540  } else {
541  logger.log(Level.SEVERE, "Attempt to get path condition with illegal chars"); // NON-NLS
542  throw new IllegalStateException("The files set rule panel path condition is not in a valid state"); // NON-NLS
543  }
544  }
545  }
546  return condition;
547  }
548 
558  FilesSet.Rule.DateCondition getDateCondition() {
559  FilesSet.Rule.DateCondition dateCondition = null;
560  if (!daysIncludedTextField.getText().isEmpty()) {
561  dateCondition = new FilesSet.Rule.DateCondition(Integer.parseInt(daysIncludedTextField.getText()));
562  }
563  return dateCondition;
564  }
565 
575  private static boolean containsOnlyLegalChars(String toBeChecked, List<String> illegalChars) {
576  for (String illegalChar : illegalChars) {
577  if (toBeChecked.contains(illegalChar)) {
578  return false;
579  }
580  }
581  return true;
582  }
583 
588  private void setComponentsForSearchType() {
589  if (!this.filesRadioButton.isSelected()) {
590  this.fullNameRadioButton.setSelected(true);
591  this.extensionRadioButton.setEnabled(false);
592  this.mimeTypeComboBox.setEnabled(false);
593  this.mimeTypeComboBox.setSelectedIndex(0);
594  this.equalitySymbolComboBox.setEnabled(false);
595  this.fileSizeComboBox.setEnabled(false);
596  this.fileSizeSpinner.setEnabled(false);
597  this.fileSizeSpinner.setValue(0);
598  this.fileSizeCheck.setEnabled(false);
599  this.fileSizeCheck.setSelected(false);
600  this.mimeCheck.setEnabled(false);
601  this.mimeCheck.setSelected(false);
602  } else {
603  if (this.nameCheck.isSelected()) {
604  this.extensionRadioButton.setEnabled(true);
605  }
606  this.fileSizeCheck.setEnabled(true);
607  this.mimeCheck.setEnabled(true);
608  }
609  }
610 
616  @SuppressWarnings("unchecked")
617  // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
618  private void initComponents() {
619 
620  nameButtonGroup = new javax.swing.ButtonGroup();
621  typeButtonGroup = new javax.swing.ButtonGroup();
622  ruleNameLabel = new javax.swing.JLabel();
623  ruleNameTextField = new javax.swing.JTextField();
624  jLabel1 = new javax.swing.JLabel();
625  nameTextField = new javax.swing.JTextField();
626  fullNameRadioButton = new javax.swing.JRadioButton();
627  extensionRadioButton = new javax.swing.JRadioButton();
628  nameRegexCheckbox = new javax.swing.JCheckBox();
629  pathTextField = new javax.swing.JTextField();
630  pathRegexCheckBox = new javax.swing.JCheckBox();
631  pathSeparatorInfoLabel = new javax.swing.JLabel();
632  jLabel5 = new javax.swing.JLabel();
633  mimeTypeComboBox = new javax.swing.JComboBox<String>();
634  equalitySymbolComboBox = new javax.swing.JComboBox<String>();
635  fileSizeComboBox = new javax.swing.JComboBox<String>();
636  fileSizeSpinner = new javax.swing.JSpinner();
637  nameCheck = new javax.swing.JCheckBox();
638  pathCheck = new javax.swing.JCheckBox();
639  mimeCheck = new javax.swing.JCheckBox();
640  fileSizeCheck = new javax.swing.JCheckBox();
641  filesRadioButton = new javax.swing.JRadioButton();
642  dirsRadioButton = new javax.swing.JRadioButton();
643  allRadioButton = new javax.swing.JRadioButton();
644  daysIncludedTextField = new javax.swing.JTextField();
645  daysIncludedLabel = new javax.swing.JLabel();
646  dateCheck = new javax.swing.JCheckBox();
647 
648  org.openide.awt.Mnemonics.setLocalizedText(ruleNameLabel, org.openide.util.NbBundle.getMessage(FilesSetRulePanel.class, "FilesSetRulePanel.ruleNameLabel.text")); // NOI18N
649 
650  ruleNameTextField.setText(org.openide.util.NbBundle.getMessage(FilesSetRulePanel.class, "FilesSetRulePanel.ruleNameTextField.text")); // NOI18N
651 
652  org.openide.awt.Mnemonics.setLocalizedText(jLabel1, org.openide.util.NbBundle.getMessage(FilesSetRulePanel.class, "FilesSetRulePanel.jLabel1.text")); // NOI18N
653 
654  nameTextField.setText(org.openide.util.NbBundle.getMessage(FilesSetRulePanel.class, "FilesSetRulePanel.nameTextField.text")); // NOI18N
655  nameTextField.setEnabled(false);
656 
657  nameButtonGroup.add(fullNameRadioButton);
658  org.openide.awt.Mnemonics.setLocalizedText(fullNameRadioButton, org.openide.util.NbBundle.getMessage(FilesSetRulePanel.class, "FilesSetRulePanel.fullNameRadioButton.text")); // NOI18N
659  fullNameRadioButton.setEnabled(false);
660 
661  nameButtonGroup.add(extensionRadioButton);
662  org.openide.awt.Mnemonics.setLocalizedText(extensionRadioButton, org.openide.util.NbBundle.getMessage(FilesSetRulePanel.class, "FilesSetRulePanel.extensionRadioButton.text")); // NOI18N
663  extensionRadioButton.setEnabled(false);
664 
665  org.openide.awt.Mnemonics.setLocalizedText(nameRegexCheckbox, org.openide.util.NbBundle.getMessage(FilesSetRulePanel.class, "FilesSetRulePanel.nameRegexCheckbox.text")); // NOI18N
666  nameRegexCheckbox.setEnabled(false);
667 
668  pathTextField.setText(org.openide.util.NbBundle.getMessage(FilesSetRulePanel.class, "FilesSetRulePanel.pathTextField.text")); // NOI18N
669  pathTextField.setEnabled(false);
670 
671  org.openide.awt.Mnemonics.setLocalizedText(pathRegexCheckBox, org.openide.util.NbBundle.getMessage(FilesSetRulePanel.class, "FilesSetRulePanel.pathRegexCheckBox.text")); // NOI18N
672  pathRegexCheckBox.setEnabled(false);
673 
674  pathSeparatorInfoLabel.setIcon(new javax.swing.ImageIcon(getClass().getResource("/org/sleuthkit/autopsy/images/info-icon-16.png"))); // NOI18N
675  org.openide.awt.Mnemonics.setLocalizedText(pathSeparatorInfoLabel, org.openide.util.NbBundle.getMessage(FilesSetRulePanel.class, "FilesSetRulePanel.pathSeparatorInfoLabel.text")); // NOI18N
676  pathSeparatorInfoLabel.setEnabled(false);
677 
678  org.openide.awt.Mnemonics.setLocalizedText(jLabel5, org.openide.util.NbBundle.getMessage(FilesSetRulePanel.class, "FilesSetRulePanel.interesting.jLabel5.text")); // NOI18N
679 
680  mimeTypeComboBox.setEditable(true);
681  mimeTypeComboBox.setModel(new javax.swing.DefaultComboBoxModel<String>(new String[] {""}));
682  mimeTypeComboBox.setEnabled(false);
683 
684  equalitySymbolComboBox.setModel(new javax.swing.DefaultComboBoxModel<String>(new String[] { "=", ">", "≥", "<", "≤" }));
685  equalitySymbolComboBox.setEnabled(false);
686 
687  fileSizeComboBox.setModel(new javax.swing.DefaultComboBoxModel<String>(new String[] { Bundle.FilesSetRulePanel_bytes(), Bundle.FilesSetRulePanel_kiloBytes(), Bundle.FilesSetRulePanel_megaBytes(), Bundle.FilesSetRulePanel_gigaBytes() }));
688  fileSizeComboBox.setEnabled(false);
689 
690  fileSizeSpinner.setModel(new javax.swing.SpinnerNumberModel(0, 0, null, 1));
691  fileSizeSpinner.setEnabled(false);
692 
693  org.openide.awt.Mnemonics.setLocalizedText(nameCheck, org.openide.util.NbBundle.getMessage(FilesSetRulePanel.class, "FilesSetRulePanel.nameCheck.text")); // NOI18N
694  nameCheck.addActionListener(new java.awt.event.ActionListener() {
695  public void actionPerformed(java.awt.event.ActionEvent evt) {
696  nameCheckActionPerformed(evt);
697  }
698  });
699 
700  org.openide.awt.Mnemonics.setLocalizedText(pathCheck, org.openide.util.NbBundle.getMessage(FilesSetRulePanel.class, "FilesSetRulePanel.pathCheck.text")); // NOI18N
701  pathCheck.addActionListener(new java.awt.event.ActionListener() {
702  public void actionPerformed(java.awt.event.ActionEvent evt) {
703  pathCheckActionPerformed(evt);
704  }
705  });
706 
707  org.openide.awt.Mnemonics.setLocalizedText(mimeCheck, org.openide.util.NbBundle.getMessage(FilesSetRulePanel.class, "FilesSetRulePanel.mimeCheck.text")); // NOI18N
708  mimeCheck.addActionListener(new java.awt.event.ActionListener() {
709  public void actionPerformed(java.awt.event.ActionEvent evt) {
710  mimeCheckActionPerformed(evt);
711  }
712  });
713 
714  org.openide.awt.Mnemonics.setLocalizedText(fileSizeCheck, org.openide.util.NbBundle.getMessage(FilesSetRulePanel.class, "FilesSetRulePanel.fileSizeCheck.text")); // NOI18N
715  fileSizeCheck.addActionListener(new java.awt.event.ActionListener() {
716  public void actionPerformed(java.awt.event.ActionEvent evt) {
717  fileSizeCheckActionPerformed(evt);
718  }
719  });
720 
721  typeButtonGroup.add(filesRadioButton);
722  org.openide.awt.Mnemonics.setLocalizedText(filesRadioButton, org.openide.util.NbBundle.getMessage(FilesSetRulePanel.class, "FilesSetRulePanel.filesRadioButton.text")); // NOI18N
723  filesRadioButton.addActionListener(new java.awt.event.ActionListener() {
724  public void actionPerformed(java.awt.event.ActionEvent evt) {
725  filesRadioButtonActionPerformed(evt);
726  }
727  });
728 
729  typeButtonGroup.add(dirsRadioButton);
730  org.openide.awt.Mnemonics.setLocalizedText(dirsRadioButton, org.openide.util.NbBundle.getMessage(FilesSetRulePanel.class, "FilesSetRulePanel.dirsRadioButton.text")); // NOI18N
731  dirsRadioButton.addActionListener(new java.awt.event.ActionListener() {
732  public void actionPerformed(java.awt.event.ActionEvent evt) {
733  dirsRadioButtonActionPerformed(evt);
734  }
735  });
736 
737  typeButtonGroup.add(allRadioButton);
738  org.openide.awt.Mnemonics.setLocalizedText(allRadioButton, org.openide.util.NbBundle.getMessage(FilesSetRulePanel.class, "FilesSetRulePanel.allRadioButton.text")); // NOI18N
739  allRadioButton.addActionListener(new java.awt.event.ActionListener() {
740  public void actionPerformed(java.awt.event.ActionEvent evt) {
741  allRadioButtonActionPerformed(evt);
742  }
743  });
744 
745  daysIncludedTextField.setEnabled(false);
746  daysIncludedTextField.setMinimumSize(new java.awt.Dimension(60, 20));
747  daysIncludedTextField.setPreferredSize(new java.awt.Dimension(60, 20));
748 
749  org.openide.awt.Mnemonics.setLocalizedText(daysIncludedLabel, org.openide.util.NbBundle.getMessage(FilesSetRulePanel.class, "FilesSetRulePanel.daysIncludedLabel.text")); // NOI18N
750 
751  org.openide.awt.Mnemonics.setLocalizedText(dateCheck, org.openide.util.NbBundle.getMessage(FilesSetRulePanel.class, "FilesSetRulePanel.dateCheck.text")); // NOI18N
752  dateCheck.addActionListener(new java.awt.event.ActionListener() {
753  public void actionPerformed(java.awt.event.ActionEvent evt) {
754  dateCheckActionPerformed(evt);
755  }
756  });
757 
758  javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
759  this.setLayout(layout);
760  layout.setHorizontalGroup(
761  layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
762  .addGroup(layout.createSequentialGroup()
763  .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
764  .addGroup(layout.createSequentialGroup()
765  .addGap(8, 8, 8)
766  .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
767  .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
768  .addComponent(ruleNameLabel)
769  .addGap(5, 5, 5)
770  .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
771  .addComponent(mimeTypeComboBox, 0, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
772  .addComponent(pathTextField)
773  .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
774  .addComponent(equalitySymbolComboBox, 0, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
775  .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
776  .addComponent(fileSizeSpinner)
777  .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
778  .addComponent(fileSizeComboBox, 0, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
779  .addGroup(layout.createSequentialGroup()
780  .addComponent(pathRegexCheckBox)
781  .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
782  .addComponent(pathSeparatorInfoLabel))
783  .addGroup(layout.createSequentialGroup()
784  .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
785  .addGroup(layout.createSequentialGroup()
786  .addComponent(daysIncludedTextField, javax.swing.GroupLayout.PREFERRED_SIZE, 69, javax.swing.GroupLayout.PREFERRED_SIZE)
787  .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
788  .addComponent(daysIncludedLabel))
789  .addComponent(ruleNameTextField, javax.swing.GroupLayout.DEFAULT_SIZE, 249, Short.MAX_VALUE)
790  .addGroup(layout.createSequentialGroup()
791  .addComponent(fullNameRadioButton)
792  .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
793  .addComponent(extensionRadioButton, javax.swing.GroupLayout.PREFERRED_SIZE, 98, javax.swing.GroupLayout.PREFERRED_SIZE)
794  .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
795  .addComponent(nameRegexCheckbox)))
796  .addGap(1, 1, 1))))
797  .addComponent(jLabel5)
798  .addGroup(layout.createSequentialGroup()
799  .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
800  .addComponent(nameCheck, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.PREFERRED_SIZE, 95, javax.swing.GroupLayout.PREFERRED_SIZE)
801  .addComponent(jLabel1))
802  .addGap(16, 16, 16)
803  .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
804  .addGroup(layout.createSequentialGroup()
805  .addComponent(filesRadioButton)
806  .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
807  .addComponent(dirsRadioButton)
808  .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
809  .addComponent(allRadioButton))
810  .addComponent(nameTextField)))))
811  .addGroup(layout.createSequentialGroup()
812  .addContainerGap()
813  .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
814  .addComponent(pathCheck)
815  .addComponent(mimeCheck)
816  .addComponent(fileSizeCheck)
817  .addComponent(dateCheck))
818  .addGap(0, 0, Short.MAX_VALUE)))
819  .addContainerGap())
820  );
821  layout.setVerticalGroup(
822  layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
823  .addGroup(layout.createSequentialGroup()
824  .addComponent(jLabel5)
825  .addGap(3, 3, 3)
826  .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING)
827  .addGroup(layout.createSequentialGroup()
828  .addComponent(jLabel1)
829  .addGap(10, 10, 10)
830  .addComponent(nameCheck))
831  .addGroup(layout.createSequentialGroup()
832  .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
833  .addComponent(filesRadioButton)
834  .addComponent(dirsRadioButton)
835  .addComponent(allRadioButton))
836  .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
837  .addComponent(nameTextField, javax.swing.GroupLayout.PREFERRED_SIZE, 20, javax.swing.GroupLayout.PREFERRED_SIZE)))
838  .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
839  .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
840  .addComponent(fullNameRadioButton)
841  .addComponent(extensionRadioButton)
842  .addComponent(nameRegexCheckbox))
843  .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
844  .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
845  .addComponent(pathTextField, javax.swing.GroupLayout.PREFERRED_SIZE, 20, javax.swing.GroupLayout.PREFERRED_SIZE)
846  .addComponent(pathCheck))
847  .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
848  .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
849  .addComponent(pathRegexCheckBox)
850  .addComponent(pathSeparatorInfoLabel))
851  .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
852  .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
853  .addComponent(mimeTypeComboBox, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
854  .addComponent(mimeCheck))
855  .addGap(11, 11, 11)
856  .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
857  .addComponent(equalitySymbolComboBox, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
858  .addComponent(fileSizeComboBox, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
859  .addComponent(fileSizeSpinner, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
860  .addComponent(fileSizeCheck))
861  .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
862  .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
863  .addComponent(daysIncludedTextField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
864  .addComponent(daysIncludedLabel)
865  .addComponent(dateCheck))
866  .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
867  .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
868  .addComponent(ruleNameTextField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
869  .addComponent(ruleNameLabel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
870  .addContainerGap())
871  );
872  }// </editor-fold>//GEN-END:initComponents
873 
874  private void nameCheckActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_nameCheckActionPerformed
875  if (!this.nameCheck.isSelected()) {
876  this.nameTextField.setEnabled(false);
877  this.nameTextField.setText("");
878  this.fullNameRadioButton.setEnabled(false);
879  this.extensionRadioButton.setEnabled(false);
880  this.nameRegexCheckbox.setEnabled(false);
881  } else {
882  this.nameTextField.setEnabled(true);
883  this.fullNameRadioButton.setEnabled(true);
884  if (this.filesRadioButton.isSelected()) {
885  this.extensionRadioButton.setEnabled(true);
886  }
887  this.nameRegexCheckbox.setEnabled(true);
888  }
889  this.setOkButton();
890  }//GEN-LAST:event_nameCheckActionPerformed
891 
892  private void pathCheckActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_pathCheckActionPerformed
893  if (!this.pathCheck.isSelected()) {
894  this.pathTextField.setEnabled(false);
895  this.pathTextField.setText("");
896  this.pathRegexCheckBox.setEnabled(false);
897  this.pathSeparatorInfoLabel.setEnabled(false);
898  } else {
899  this.pathTextField.setEnabled(true);
900  this.pathRegexCheckBox.setEnabled(true);
901  this.pathSeparatorInfoLabel.setEnabled(true);
902  }
903  this.setOkButton();
904  }//GEN-LAST:event_pathCheckActionPerformed
905 
906  private void filesRadioButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_filesRadioButtonActionPerformed
907 
908  this.setComponentsForSearchType();
909  }//GEN-LAST:event_filesRadioButtonActionPerformed
910 
911  private void dirsRadioButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_dirsRadioButtonActionPerformed
912  this.setComponentsForSearchType();
913  }//GEN-LAST:event_dirsRadioButtonActionPerformed
914 
915  private void allRadioButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_allRadioButtonActionPerformed
916  this.setComponentsForSearchType();
917  }//GEN-LAST:event_allRadioButtonActionPerformed
918 
919  private void dateCheckActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_dateCheckActionPerformed
920  if (!this.dateCheck.isSelected()) {
921  this.daysIncludedTextField.setEnabled(false);
922  this.daysIncludedLabel.setEnabled(false);
923  this.daysIncludedTextField.setText("");
924  } else {
925  this.daysIncludedTextField.setEnabled(true);
926  this.daysIncludedLabel.setEnabled(true);
927  }
928  this.setOkButton();
929  }//GEN-LAST:event_dateCheckActionPerformed
930 
931  private void fileSizeCheckActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_fileSizeCheckActionPerformed
932  if (!this.fileSizeCheck.isSelected()) {
933  this.fileSizeComboBox.setEnabled(false);
934  this.fileSizeSpinner.setEnabled(false);
935  this.fileSizeSpinner.setValue(0);
936  this.equalitySymbolComboBox.setEnabled(false);
937  } else {
938  this.fileSizeComboBox.setEnabled(true);
939  this.fileSizeSpinner.setEnabled(true);
940  this.equalitySymbolComboBox.setEnabled(true);
941  }
942  this.setOkButton();
943  }//GEN-LAST:event_fileSizeCheckActionPerformed
944 
945  private void mimeCheckActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_mimeCheckActionPerformed
946  if (!this.mimeCheck.isSelected()) {
947  this.mimeTypeComboBox.setEnabled(false);
948  this.mimeTypeComboBox.setSelectedIndex(0);
949  } else {
950  this.mimeTypeComboBox.setEnabled(true);
951  }
952  this.setOkButton();
953  }//GEN-LAST:event_mimeCheckActionPerformed
954 
955  // Variables declaration - do not modify//GEN-BEGIN:variables
956  private javax.swing.JRadioButton allRadioButton;
957  private javax.swing.JCheckBox dateCheck;
958  private javax.swing.JLabel daysIncludedLabel;
959  private javax.swing.JTextField daysIncludedTextField;
960  private javax.swing.JRadioButton dirsRadioButton;
961  private javax.swing.JComboBox<String> equalitySymbolComboBox;
962  private javax.swing.JRadioButton extensionRadioButton;
963  private javax.swing.JCheckBox fileSizeCheck;
964  private javax.swing.JComboBox<String> fileSizeComboBox;
965  private javax.swing.JSpinner fileSizeSpinner;
966  private javax.swing.JRadioButton filesRadioButton;
967  private javax.swing.JRadioButton fullNameRadioButton;
968  private javax.swing.JLabel jLabel1;
969  private javax.swing.JLabel jLabel5;
970  private javax.swing.JCheckBox mimeCheck;
971  private javax.swing.JComboBox<String> mimeTypeComboBox;
972  private javax.swing.ButtonGroup nameButtonGroup;
973  private javax.swing.JCheckBox nameCheck;
974  private javax.swing.JCheckBox nameRegexCheckbox;
975  private javax.swing.JTextField nameTextField;
976  private javax.swing.JCheckBox pathCheck;
977  private javax.swing.JCheckBox pathRegexCheckBox;
978  private javax.swing.JLabel pathSeparatorInfoLabel;
979  private javax.swing.JTextField pathTextField;
980  private javax.swing.JLabel ruleNameLabel;
981  private javax.swing.JTextField ruleNameTextField;
982  private javax.swing.ButtonGroup typeButtonGroup;
983  // End of variables declaration//GEN-END:variables
984 }

Copyright © 2012-2016 Basis Technology. Generated on: Mon Jun 18 2018
This work is licensed under a Creative Commons Attribution-Share Alike 3.0 United States License.