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);