19 package org.sleuthkit.autopsy.filesearch;
21 import java.awt.Component;
22 import java.awt.event.ActionListener;
23 import java.beans.PropertyChangeEvent;
24 import java.beans.PropertyChangeListener;
25 import java.text.DateFormat;
26 import java.text.ParseException;
27 import java.text.SimpleDateFormat;
28 import java.util.ArrayList;
29 import java.util.Calendar;
30 import java.util.Date;
31 import java.util.EnumSet;
32 import java.util.Iterator;
33 import java.util.List;
35 import java.util.SimpleTimeZone;
36 import java.util.TimeZone;
37 import javax.swing.JLabel;
38 import javax.swing.JList;
39 import javax.swing.JSeparator;
40 import javax.swing.ListCellRenderer;
41 import javax.swing.SwingUtilities;
42 import javax.swing.border.EmptyBorder;
43 import org.openide.util.NbBundle;
45 import org.openide.util.NbBundle.Messages;
53 class DateSearchFilter
extends AbstractFileSearchFilter<DateSearchPanel> {
55 private static final String NONE_SELECTED_MESSAGE = NbBundle.getMessage(DateSearchFilter.class,
"DateSearchFilter.noneSelectedMsg.text");
56 private static final DateFormat DATE_FORMAT =
new SimpleDateFormat(
"MM/dd/yyyy");
57 private static final String SEPARATOR =
"SEPARATOR";
59 private static final Set<Case.Events> CASE_EVENTS_OF_INTEREST = EnumSet.of(Case.Events.CURRENT_CASE,
60 Case.Events.DATA_SOURCE_ADDED, Case.Events.DATA_SOURCE_DELETED);
66 this(
new DateSearchPanel(DATE_FORMAT, DateSearchFilter.createTimeZoneList()));
69 private DateSearchFilter(DateSearchPanel panel) {
71 Case.addEventTypeSubscriber(CASE_EVENTS_OF_INTEREST, this.
new CasePropertyChangeListener());
75 public boolean isEnabled() {
76 return this.getComponent().getDateCheckBox().isSelected();
80 public String getPredicate() throws FilterValidationException {
81 String query =
"NULL";
82 DateSearchPanel panel = this.getComponent();
86 String startDateValue = panel.getFromDate();
87 Calendar startDate = getCalendarDate(startDateValue);
88 if (!startDateValue.isEmpty()) {
89 if (startDate != null) {
90 fromDate = startDate.getTimeInMillis() / 1000;
95 String endDateValue = panel.getToDate();
96 Calendar endDate = getCalendarDate(endDateValue);
97 if (!endDateValue.isEmpty()) {
98 if (endDate != null) {
99 toDate = endDate.getTimeInMillis() / 1000;
103 final boolean modifiedChecked = panel.getModifiedCheckBox().isSelected();
104 final boolean changedChecked = panel.getChangedCheckBox().isSelected();
105 final boolean accessedChecked = panel.getAccessedCheckBox().isSelected();
106 final boolean createdChecked = panel.getCreatedCheckBox().isSelected();
108 if (modifiedChecked || changedChecked || accessedChecked || createdChecked) {
110 if (modifiedChecked) {
111 query +=
" OR (mtime BETWEEN " + fromDate +
" AND " + toDate +
")";
114 if (changedChecked) {
115 query +=
" OR (ctime BETWEEN " + fromDate +
" AND " + toDate +
")";
118 if (accessedChecked) {
119 query +=
" OR (atime BETWEEN " + fromDate +
" AND " + toDate +
")";
122 if (createdChecked) {
123 query +=
" OR (crtime BETWEEN " + fromDate +
" AND " + toDate +
")";
127 throw new FilterValidationException(NONE_SELECTED_MESSAGE);
134 private void updateTimeZoneList() {
135 this.getComponent().setTimeZones(DateSearchFilter.createTimeZoneList());
138 private static List<String> createTimeZoneList() {
140 List<String> timeZones =
new ArrayList<>();
144 Case currentCase = Case.getCurrentCaseThrows();
146 Set<TimeZone> caseTimeZones = currentCase.getTimeZones();
147 Iterator<TimeZone> iterator = caseTimeZones.iterator();
148 while (iterator.hasNext()) {
149 TimeZone zone = iterator.next();
150 int offset = zone.getRawOffset() / 1000;
151 int hour = offset / 3600;
152 int minutes = (offset % 3600) / 60;
153 String item = String.format(
"(GMT%+d:%02d) %s", hour, minutes, zone.getID());
157 if (caseTimeZones.size() > 0) {
158 timeZones.add(SEPARATOR);
162 String[] ids = SimpleTimeZone.getAvailableIDs();
163 for (String
id : ids) {
164 TimeZone zone = TimeZone.getTimeZone(
id);
165 int offset = zone.getRawOffset() / 1000;
166 int hour = offset / 3600;
167 int minutes = (offset % 3600) / 60;
168 String item = String.format(
"(GMT%+d:%02d) %s", hour, minutes,
id);
171 }
catch (NoCurrentCaseException ex) {
178 private TimeZone getSelectedTimeZone() {
179 String tz = this.getComponent().getTimeZoneComboBox().getSelectedItem().toString();
180 String tzID = tz.substring(tz.indexOf(
" ") + 1);
181 TimeZone selectedTZ = TimeZone.getTimeZone(tzID);
185 private Calendar getCalendarDate(String dateValue) {
186 TimeZone selectedTZ = getSelectedTimeZone();
187 Calendar inputDate = null;
189 DateFormat sdf =
new SimpleDateFormat(
"MM/dd/yyyy");
190 sdf.setTimeZone(selectedTZ);
191 Date temp = sdf.parse(dateValue);
193 inputDate = Calendar.getInstance(
new SimpleTimeZone(0,
"GMT"));
194 inputDate.setTime(temp);
195 }
catch (ParseException ex) {
202 public void addActionListener(ActionListener l) {
203 getComponent().addDateChangeListener();
208 "DateSearchFilter.errorMessage.endDateBeforeStartDate=The end date should be after the start date.",
209 "DateSearchFilter.errorMessage.noCheckboxSelected=At least one date type checkbox must be selected."
211 public boolean isValid() {
213 DateSearchPanel panel = this.getComponent();
214 Calendar startDate = getCalendarDate(panel.getFromDate());
215 Calendar endDate = getCalendarDate(panel.getToDate());
217 if ((startDate != null && startDate.after(endDate)) || (endDate != null && endDate.before(startDate))) {
218 setLastError(Bundle.DateSearchFilter_errorMessage_endDateBeforeStartDate());
222 if (!panel.isValidSearch()) {
223 setLastError(Bundle.DateSearchFilter_errorMessage_noCheckboxSelected());
233 static class ComboBoxRenderer
extends JLabel implements ListCellRenderer<String> {
235 JSeparator separator;
239 setBorder(
new EmptyBorder(1, 1, 1, 1));
240 separator =
new JSeparator(JSeparator.HORIZONTAL);
244 public Component getListCellRendererComponent(JList<? extends String> list, String value,
int index,
boolean isSelected,
boolean cellHasFocus) {
245 String str = (value == null) ?
"" : value;
246 if (SEPARATOR.equals(str)) {
250 setBackground(list.getSelectionBackground());
251 setForeground(list.getSelectionForeground());
253 setBackground(list.getBackground());
254 setForeground(list.getForeground());
256 setFont(list.getFont());
266 switch (
Case.
Events.valueOf(evt.getPropertyName())) {
268 Object newValue = evt.getNewValue();
269 if (null != newValue) {
273 SwingUtilities.invokeLater(DateSearchFilter.this::updateTimeZoneList);
276 case DATA_SOURCE_ADDED:
277 case DATA_SOURCE_DELETED:
286 SwingUtilities.invokeLater(DateSearchFilter.this::updateTimeZoneList);
void propertyChange(PropertyChangeEvent evt)
static Case getCurrentCaseThrows()