19 package org.sleuthkit.autopsy.keywordsearch;
21 import java.beans.PropertyChangeListener;
22 import java.beans.PropertyChangeSupport;
24 import java.util.ArrayList;
25 import java.util.Date;
26 import java.util.LinkedHashMap;
27 import java.util.List;
29 import java.util.logging.Level;
30 import org.openide.util.NbBundle;
38 abstract class KeywordSearchList {
40 protected static final Logger LOGGER = Logger.getLogger(KeywordSearchList.class.getName());
47 private static final String BOUNDARY_CHARACTERS =
"[ \t\r\n\\.\\-\\?\\,\\;\\\\!\\:\\[\\]\\/\\(\\)\\\"\\\'\\>\\{\\}]";
48 private static final String PHONE_NUMBER_REGEX = BOUNDARY_CHARACTERS +
"(\\([0-9]{3}\\)|[0-9]{3})([ \\-\\.])[0-9]{3}([ \\-\\.])[0-9]{4}" + BOUNDARY_CHARACTERS;
49 private static final String IP_ADDRESS_REGEX = BOUNDARY_CHARACTERS +
"(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\\.){3}(1[0-9]{2}|2[0-4][0-9]|25[0-5]|[1-9][0-9]|[0-9])" + BOUNDARY_CHARACTERS;
50 private static final String EMAIL_ADDRESS_REGEX =
"(\\{?)[a-zA-Z0-9%+_\\-]+(\\.[a-zA-Z0-9%+_\\-]+)*(\\}?)\\@([a-zA-Z0-9]([a-zA-Z0-9\\-]*[a-zA-Z0-9])?\\.)+[a-zA-Z]{2,4}";
51 private static final String URL_REGEX =
"(((((h|H)(t|T))|(f|F))(t|T)(p|P)(s|S?)\\:\\/\\/)|(w|W){3,3}\\.)[a-zA-Z0-9\\-\\.]+\\.([a-zA-Z]{2,5})(\\:[0-9]+)*(\\/($|[a-zA-Z0-9\\.\\,\\;\\?\\'\\\\+&%\\$#\\=~_\\-]+))*";
62 private static final String CCN_REGEX =
"(%?)(B?)([0-9][ \\-]*?){12,19}(\\^?)";
64 protected String filePath;
65 Map<String, KeywordList> theLists;
67 PropertyChangeSupport changeSupport;
68 protected List<String> lockedLists;
70 KeywordSearchList(String filePath) {
71 this.filePath = filePath;
72 theLists =
new LinkedHashMap<>();
73 lockedLists =
new ArrayList<>();
74 changeSupport =
new PropertyChangeSupport(
this);
95 void fireLanguagesEvent(LanguagesEvent event) {
97 changeSupport.firePropertyChange(event.toString(), null, null);
98 }
catch (Exception e) {
99 LOGGER.log(Level.SEVERE,
"KeywordSearchListsAbstract listener threw exception", e);
103 public void addPropertyChangeListener(PropertyChangeListener listener) {
104 changeSupport.addPropertyChangeListener(listener);
107 public void removePropertyChangeListener(PropertyChangeListener listener) {
108 changeSupport.removePropertyChangeListener(listener);
111 private void prepopulateLists() {
112 if (!theLists.isEmpty()) {
116 List<Keyword> phones =
new ArrayList<>();
117 phones.add(
new Keyword(PHONE_NUMBER_REGEX,
false, BlackboardAttribute.ATTRIBUTE_TYPE.TSK_PHONE_NUMBER));
118 lockedLists.add(
"Phone Numbers");
119 addList(
"Phone Numbers", phones,
false,
false,
true);
122 List<Keyword> ips =
new ArrayList<>();
123 ips.add(
new Keyword(IP_ADDRESS_REGEX,
false, BlackboardAttribute.ATTRIBUTE_TYPE.TSK_IP_ADDRESS));
124 lockedLists.add(
"IP Addresses");
125 addList(
"IP Addresses", ips,
false,
false,
true);
128 List<Keyword> emails =
new ArrayList<>();
129 emails.add(
new Keyword(EMAIL_ADDRESS_REGEX,
false, BlackboardAttribute.ATTRIBUTE_TYPE.TSK_EMAIL));
130 lockedLists.add(
"Email Addresses");
131 addList(
"Email Addresses", emails,
true,
false,
true);
134 List<Keyword> urls =
new ArrayList<>();
135 urls.add(
new Keyword(URL_REGEX,
false, BlackboardAttribute.ATTRIBUTE_TYPE.TSK_URL));
136 lockedLists.add(
"URLs");
137 addList(
"URLs", urls,
false,
false,
true);
140 List<Keyword> ccns =
new ArrayList<>();
141 ccns.add(
new Keyword(CCN_REGEX,
false, BlackboardAttribute.ATTRIBUTE_TYPE.TSK_CARD_NUMBER));
142 lockedLists.add(
"Credit Card Numbers");
143 addList(
"Credit Card Numbers", ccns,
false,
false,
true);
149 public void reload() {
150 boolean created =
false;
158 List<String> toClear =
new ArrayList<>();
159 for (String list : theLists.keySet()) {
160 if (theLists.get(list).isEditable() ==
false) {
164 for (String clearList : toClear) {
165 theLists.remove(clearList);
168 if (!listFileExists()) {
175 if (!load() && !created) {
181 public List<KeywordList> getListsL() {
182 List<KeywordList> ret =
new ArrayList<>();
183 for (KeywordList list : theLists.values()) {
189 public List<KeywordList> getListsL(
boolean locked) {
190 List<KeywordList> ret =
new ArrayList<>();
191 for (KeywordList list : theLists.values()) {
192 if (list.isEditable().equals(locked)) {
204 public List<String> getListNames() {
205 return new ArrayList<>(theLists.keySet());
215 public List<String> getListNames(
boolean locked) {
216 ArrayList<String> lists =
new ArrayList<>();
217 for (String listName : theLists.keySet()) {
218 KeywordList list = theLists.get(listName);
219 if (locked == list.isEditable()) {
234 public KeywordList getListWithKeyword(String keyword) {
235 KeywordList found = null;
236 for (KeywordList list : theLists.values()) {
237 if (list.hasSearchTerm(keyword)) {
250 int getNumberLists() {
251 return theLists.size();
261 public int getNumberLists(
boolean locked) {
263 for (String listName : theLists.keySet()) {
264 KeywordList list = theLists.get(listName);
265 if (locked == list.isEditable()) {
279 public KeywordList getList(String name) {
280 return theLists.get(name);
290 boolean listExists(String name) {
291 return getList(name) != null;
304 boolean addList(String name, List<Keyword> newList,
boolean useForIngest,
boolean ingestMessages,
boolean locked) {
305 boolean replaced =
false;
306 KeywordList curList = getList(name);
307 final Date now =
new Date();
309 if (curList == null) {
310 theLists.put(name,
new KeywordList(name, now, now, useForIngest, ingestMessages, newList, locked));
312 changeSupport.firePropertyChange(ListsEvt.LIST_ADDED.toString(), null, name);
313 }
catch (Exception e) {
314 LOGGER.log(Level.SEVERE,
"KeywordSearchListsAbstract listener threw exception", e);
315 MessageNotifyUtil.Notify.show(
316 NbBundle.getMessage(
this.getClass(),
"KeywordSearchListsAbstract.moduleErr"),
317 NbBundle.getMessage(
this.getClass(),
"KeywordSearchListsAbstract.addList.errMsg1.msg"),
318 MessageNotifyUtil.MessageType.ERROR);
321 theLists.put(name,
new KeywordList(name, curList.getDateCreated(), now, useForIngest, ingestMessages, newList, locked));
325 changeSupport.firePropertyChange(ListsEvt.LIST_UPDATED.toString(), null, name);
326 }
catch (Exception e) {
327 LOGGER.log(Level.SEVERE,
"KeywordSearchListsAbstract listener threw exception", e);
328 MessageNotifyUtil.Notify.show(
329 NbBundle.getMessage(
this.getClass(),
"KeywordSearchListsAbstract.moduleErr"),
330 NbBundle.getMessage(
this.getClass(),
"KeywordSearchListsAbstract.addList.errMsg2.msg"),
331 MessageNotifyUtil.MessageType.ERROR);
338 boolean addList(String name, List<Keyword> newList,
boolean useForIngest,
boolean ingestMessages) {
340 boolean isLocked = this.lockedLists.contains(name);
341 return addList(name, newList, useForIngest, ingestMessages, isLocked);
344 boolean addList(String name, List<Keyword> newList) {
345 return addList(name, newList,
true,
true);
348 boolean addList(KeywordList list) {
349 return addList(list.getName(), list.getKeywords(), list.getUseForIngest(), list.getIngestMessages(), list.isEditable());
359 boolean saveLists(List<KeywordList> lists) {
360 List<KeywordList> overwritten =
new ArrayList<>();
361 List<KeywordList> newLists =
new ArrayList<>();
362 for (KeywordList list : lists) {
363 if (this.listExists(list.getName())) {
364 overwritten.add(list);
368 theLists.put(list.getName(), list);
370 boolean saved = save(
true);
372 for (KeywordList list : newLists) {
374 changeSupport.firePropertyChange(ListsEvt.LIST_ADDED.toString(), null, list.getName());
375 }
catch (Exception e) {
376 LOGGER.log(Level.SEVERE,
"KeywordSearchListsAbstract listener threw exception", e);
377 MessageNotifyUtil.Notify.show(
378 NbBundle.getMessage(
this.getClass(),
"KeywordSearchListsAbstract.moduleErr"),
379 NbBundle.getMessage(
this.getClass(),
"KeywordSearchListsAbstract.saveList.errMsg1.msg"),
380 MessageNotifyUtil.MessageType.ERROR);
383 for (KeywordList over : overwritten) {
385 changeSupport.firePropertyChange(ListsEvt.LIST_UPDATED.toString(), null, over.getName());
386 }
catch (Exception e) {
387 LOGGER.log(Level.SEVERE,
"KeywordSearchListsAbstract listener threw exception", e);
388 MessageNotifyUtil.Notify.show(
389 NbBundle.getMessage(
this.getClass(),
"KeywordSearchListsAbstract.moduleErr"),
390 NbBundle.getMessage(
this.getClass(),
"KeywordSearchListsAbstract.saveList.errMsg2.msg"),
391 MessageNotifyUtil.MessageType.ERROR);
406 boolean writeLists(List<KeywordList> lists) {
407 List<KeywordList> overwritten =
new ArrayList<>();
408 List<KeywordList> newLists =
new ArrayList<>();
409 for (KeywordList list : lists) {
410 if (this.listExists(list.getName())) {
411 overwritten.add(list);
415 theLists.put(list.getName(), list);
418 for (KeywordList list : newLists) {
421 changeSupport.firePropertyChange(ListsEvt.LIST_ADDED.toString(), null, list.getName());
422 }
catch (Exception e) {
423 LOGGER.log(Level.SEVERE,
"KeywordSearchListsAbstract listener threw exception", e);
424 MessageNotifyUtil.Notify.show(
425 NbBundle.getMessage(
this.getClass(),
"KeywordSearchListsAbstract.moduleErr"),
426 NbBundle.getMessage(
this.getClass(),
"KeywordSearchListsAbstract.writeLists.errMsg1.msg"),
427 MessageNotifyUtil.MessageType.ERROR);
431 for (KeywordList over : overwritten) {
434 changeSupport.firePropertyChange(ListsEvt.LIST_UPDATED.toString(), null, over.getName());
435 }
catch (Exception e) {
436 LOGGER.log(Level.SEVERE,
"KeywordSearchListsAbstract listener threw exception", e);
437 MessageNotifyUtil.Notify.show(
438 NbBundle.getMessage(
this.getClass(),
"KeywordSearchListsAbstract.moduleErr"),
439 NbBundle.getMessage(
this.getClass(),
"KeywordSearchListsAbstract.writeLists.errMsg2.msg"),
440 MessageNotifyUtil.MessageType.ERROR);
454 boolean deleteList(String name) {
455 KeywordList delList = getList(name);
456 if (delList != null && !delList.isEditable()) {
457 theLists.remove(name);
461 changeSupport.firePropertyChange(ListsEvt.LIST_DELETED.toString(), null, name);
462 }
catch (Exception e) {
463 LOGGER.log(Level.SEVERE,
"KeywordSearchListsAbstract listener threw exception", e);
464 MessageNotifyUtil.Notify.show(
465 NbBundle.getMessage(
this.getClass(),
"KeywordSearchListsAbstract.moduleErr"),
466 NbBundle.getMessage(
this.getClass(),
"KeywordSearchListsAbstract.deleteList.errMsg1.msg"),
467 MessageNotifyUtil.MessageType.ERROR);
476 public abstract boolean save();
484 public abstract boolean save(
boolean isExport);
489 public abstract boolean load();
491 private boolean listFileExists() {
492 File f =
new File(filePath);
493 return f.exists() && f.canRead() && f.canWrite();
496 public void setUseForIngest(String key,
boolean flag) {
497 theLists.get(key).setUseForIngest(flag);