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     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\\.\\,\\;\\?\\'\\\\+&%\\$#\\=~_\\-]+))*";  
 
   61     private static final String CCN_REGEX = 
"(%?)(B?)([0-9][ \\-]*?){12,19}(\\^?)";  
 
   63     protected String filePath;
 
   64     Map<String, KeywordList> theLists; 
 
   66     PropertyChangeSupport changeSupport;
 
   67     protected List<String> lockedLists;
 
   69     KeywordSearchList(String filePath) {
 
   70         this.filePath = filePath;
 
   71         theLists = 
new LinkedHashMap<>();
 
   72         lockedLists = 
new ArrayList<>();
 
   73         changeSupport = 
new PropertyChangeSupport(
this);
 
   94     void fireLanguagesEvent(LanguagesEvent event) {
 
   96             changeSupport.firePropertyChange(event.toString(), null, null);
 
   97         } 
catch (Exception e) {
 
   98             LOGGER.log(Level.SEVERE, 
"KeywordSearchListsAbstract listener threw exception", e); 
 
  102     public void addPropertyChangeListener(PropertyChangeListener listener) {
 
  103         changeSupport.addPropertyChangeListener(listener);
 
  106     public void removePropertyChangeListener(PropertyChangeListener listener) {
 
  107         changeSupport.removePropertyChangeListener(listener);
 
  110     private void prepopulateLists() {
 
  111         if (!theLists.isEmpty()) {
 
  115         List<Keyword> phones = 
new ArrayList<>();
 
  116         phones.add(
new Keyword(PHONE_NUMBER_REGEX, 
false, BlackboardAttribute.ATTRIBUTE_TYPE.TSK_PHONE_NUMBER));
 
  117         lockedLists.add(
"Phone Numbers");
 
  118         addList(
"Phone Numbers", phones, 
false, 
false, 
true);
 
  121         List<Keyword> ips = 
new ArrayList<>();
 
  122         ips.add(
new Keyword(IP_ADDRESS_REGEX, 
false, BlackboardAttribute.ATTRIBUTE_TYPE.TSK_IP_ADDRESS));
 
  123         lockedLists.add(
"IP Addresses");
 
  124         addList(
"IP Addresses", ips, 
false, 
false, 
true);
 
  127         List<Keyword> emails = 
new ArrayList<>();
 
  128         emails.add(
new Keyword(EMAIL_ADDRESS_REGEX, 
false, BlackboardAttribute.ATTRIBUTE_TYPE.TSK_EMAIL));
 
  129         lockedLists.add(
"Email Addresses");
 
  130         addList(
"Email Addresses", emails, 
true, 
false, 
true);
 
  133         List<Keyword> urls = 
new ArrayList<>();
 
  134         urls.add(
new Keyword(URL_REGEX, 
false, BlackboardAttribute.ATTRIBUTE_TYPE.TSK_URL));
 
  135         lockedLists.add(
"URLs");
 
  136         addList(
"URLs", urls, 
false, 
false, 
true);
 
  139         List<Keyword> ccns = 
new ArrayList<>();
 
  140         ccns.add(
new Keyword(CCN_REGEX, 
false, BlackboardAttribute.ATTRIBUTE_TYPE.TSK_CARD_NUMBER));
 
  141         lockedLists.add(
"Credit Card Numbers");
 
  142         addList(
"Credit Card Numbers", ccns, 
false, 
false, 
true);
 
  148     public void reload() {
 
  149         boolean created = 
false;
 
  157         List<String> toClear = 
new ArrayList<>();
 
  158         for (String list : theLists.keySet()) {
 
  159             if (theLists.get(list).isEditable() == 
false) {
 
  163         for (String clearList : toClear) {
 
  164             theLists.remove(clearList);
 
  167         if (!listFileExists()) {
 
  174         if (!load() && !created) {
 
  180     public List<KeywordList> getListsL() {
 
  181         List<KeywordList> ret = 
new ArrayList<>();
 
  182         for (KeywordList list : theLists.values()) {
 
  188     public List<KeywordList> getListsL(
boolean locked) {
 
  189         List<KeywordList> ret = 
new ArrayList<>();
 
  190         for (KeywordList list : theLists.values()) {
 
  191             if (list.isEditable().equals(locked)) {
 
  203     public List<String> getListNames() {
 
  204         return new ArrayList<>(theLists.keySet());
 
  214     public List<String> getListNames(
boolean locked) {
 
  215         ArrayList<String> lists = 
new ArrayList<>();
 
  216         for (String listName : theLists.keySet()) {
 
  217             KeywordList list = theLists.get(listName);
 
  218             if (locked == list.isEditable()) {
 
  233     public KeywordList getListWithKeyword(String keyword) {
 
  234         KeywordList found = null;
 
  235         for (KeywordList list : theLists.values()) {
 
  236             if (list.hasSearchTerm(keyword)) {
 
  249     int getNumberLists() {
 
  250         return theLists.size();
 
  260     public int getNumberLists(
boolean locked) {
 
  262         for (String listName : theLists.keySet()) {
 
  263             KeywordList list = theLists.get(listName);
 
  264             if (locked == list.isEditable()) {
 
  278     public KeywordList getList(String name) {
 
  279         return theLists.get(name);
 
  289     boolean listExists(String name) {
 
  290         return getList(name) != null;
 
  303     boolean addList(String name, List<Keyword> newList, 
boolean useForIngest, 
boolean ingestMessages, 
boolean locked) {
 
  304         boolean replaced = 
false;
 
  305         KeywordList curList = getList(name);
 
  306         final Date now = 
new Date();
 
  308         if (curList == null) {
 
  309             theLists.put(name, 
new KeywordList(name, now, now, useForIngest, ingestMessages, newList, locked));
 
  311                 changeSupport.firePropertyChange(ListsEvt.LIST_ADDED.toString(), null, name);
 
  312             } 
catch (Exception e) {
 
  313                 LOGGER.log(Level.SEVERE, 
"KeywordSearchListsAbstract listener threw exception", e); 
 
  314                 MessageNotifyUtil.Notify.show(
 
  315                         NbBundle.getMessage(
this.getClass(), 
"KeywordSearchListsAbstract.moduleErr"),
 
  316                         NbBundle.getMessage(
this.getClass(), 
"KeywordSearchListsAbstract.addList.errMsg1.msg"),
 
  317                         MessageNotifyUtil.MessageType.ERROR);
 
  320             theLists.put(name, 
new KeywordList(name, curList.getDateCreated(), now, useForIngest, ingestMessages, newList, locked));
 
  324                 changeSupport.firePropertyChange(ListsEvt.LIST_UPDATED.toString(), null, name);
 
  325             } 
catch (Exception e) {
 
  326                 LOGGER.log(Level.SEVERE, 
"KeywordSearchListsAbstract listener threw exception", e); 
 
  327                 MessageNotifyUtil.Notify.show(
 
  328                         NbBundle.getMessage(
this.getClass(), 
"KeywordSearchListsAbstract.moduleErr"),
 
  329                         NbBundle.getMessage(
this.getClass(), 
"KeywordSearchListsAbstract.addList.errMsg2.msg"),
 
  330                         MessageNotifyUtil.MessageType.ERROR);
 
  337     boolean addList(String name, List<Keyword> newList, 
boolean useForIngest, 
boolean ingestMessages) {
 
  339         boolean isLocked = this.lockedLists.contains(name);
 
  340         return addList(name, newList, useForIngest, ingestMessages, isLocked);
 
  343     boolean addList(String name, List<Keyword> newList) {
 
  344         return addList(name, newList, 
true, 
true);
 
  347     boolean addList(KeywordList list) {
 
  348         return addList(list.getName(), list.getKeywords(), list.getUseForIngest(), list.getIngestMessages(), list.isEditable());
 
  358     boolean saveLists(List<KeywordList> lists) {
 
  359         List<KeywordList> overwritten = 
new ArrayList<>();
 
  360         List<KeywordList> newLists = 
new ArrayList<>();
 
  361         for (KeywordList list : lists) {
 
  362             if (this.listExists(list.getName())) {
 
  363                 overwritten.add(list);
 
  367             theLists.put(list.getName(), list);
 
  369         boolean saved = save(
true);
 
  371             for (KeywordList list : newLists) {
 
  373                     changeSupport.firePropertyChange(ListsEvt.LIST_ADDED.toString(), null, list.getName());
 
  374                 } 
catch (Exception e) {
 
  375                     LOGGER.log(Level.SEVERE, 
"KeywordSearchListsAbstract listener threw exception", e); 
 
  376                     MessageNotifyUtil.Notify.show(
 
  377                             NbBundle.getMessage(
this.getClass(), 
"KeywordSearchListsAbstract.moduleErr"),
 
  378                             NbBundle.getMessage(
this.getClass(), 
"KeywordSearchListsAbstract.saveList.errMsg1.msg"),
 
  379                             MessageNotifyUtil.MessageType.ERROR);
 
  382             for (KeywordList over : overwritten) {
 
  384                     changeSupport.firePropertyChange(ListsEvt.LIST_UPDATED.toString(), null, over.getName());
 
  385                 } 
catch (Exception e) {
 
  386                     LOGGER.log(Level.SEVERE, 
"KeywordSearchListsAbstract listener threw exception", e); 
 
  387                     MessageNotifyUtil.Notify.show(
 
  388                             NbBundle.getMessage(
this.getClass(), 
"KeywordSearchListsAbstract.moduleErr"),
 
  389                             NbBundle.getMessage(
this.getClass(), 
"KeywordSearchListsAbstract.saveList.errMsg2.msg"),
 
  390                             MessageNotifyUtil.MessageType.ERROR);
 
  405     boolean writeLists(List<KeywordList> lists) {
 
  406         List<KeywordList> overwritten = 
new ArrayList<>();
 
  407         List<KeywordList> newLists = 
new ArrayList<>();
 
  408         for (KeywordList list : lists) {
 
  409             if (this.listExists(list.getName())) {
 
  410                 overwritten.add(list);
 
  414             theLists.put(list.getName(), list);
 
  417         for (KeywordList list : newLists) {
 
  420                 changeSupport.firePropertyChange(ListsEvt.LIST_ADDED.toString(), null, list.getName());
 
  421             } 
catch (Exception e) {
 
  422                 LOGGER.log(Level.SEVERE, 
"KeywordSearchListsAbstract listener threw exception", e); 
 
  423                 MessageNotifyUtil.Notify.show(
 
  424                         NbBundle.getMessage(
this.getClass(), 
"KeywordSearchListsAbstract.moduleErr"),
 
  425                         NbBundle.getMessage(
this.getClass(), 
"KeywordSearchListsAbstract.writeLists.errMsg1.msg"),
 
  426                         MessageNotifyUtil.MessageType.ERROR);
 
  430         for (KeywordList over : overwritten) {
 
  433                 changeSupport.firePropertyChange(ListsEvt.LIST_UPDATED.toString(), null, over.getName());
 
  434             } 
catch (Exception e) {
 
  435                 LOGGER.log(Level.SEVERE, 
"KeywordSearchListsAbstract listener threw exception", e); 
 
  436                 MessageNotifyUtil.Notify.show(
 
  437                         NbBundle.getMessage(
this.getClass(), 
"KeywordSearchListsAbstract.moduleErr"),
 
  438                         NbBundle.getMessage(
this.getClass(), 
"KeywordSearchListsAbstract.writeLists.errMsg2.msg"),
 
  439                         MessageNotifyUtil.MessageType.ERROR);
 
  453     boolean deleteList(String name) {
 
  454         KeywordList delList = getList(name);
 
  455         if (delList != null && !delList.isEditable()) {
 
  456             theLists.remove(name);
 
  460             changeSupport.firePropertyChange(ListsEvt.LIST_DELETED.toString(), null, name);
 
  461         } 
catch (Exception e) {
 
  462             LOGGER.log(Level.SEVERE, 
"KeywordSearchListsAbstract listener threw exception", e); 
 
  463             MessageNotifyUtil.Notify.show(
 
  464                     NbBundle.getMessage(
this.getClass(), 
"KeywordSearchListsAbstract.moduleErr"),
 
  465                     NbBundle.getMessage(
this.getClass(), 
"KeywordSearchListsAbstract.deleteList.errMsg1.msg"),
 
  466                     MessageNotifyUtil.MessageType.ERROR);
 
  475     public abstract boolean save();
 
  483     public abstract boolean save(
boolean isExport);
 
  488     public abstract boolean load();
 
  490     private boolean listFileExists() {
 
  491         File f = 
new File(filePath);
 
  492         return f.exists() && f.canRead() && f.canWrite();
 
  495     public void setUseForIngest(String key, 
boolean flag) {
 
  496         theLists.get(key).setUseForIngest(flag);