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());
 
   42     private static final String PHONE_NUMBER_REGEX = 
"[(]{0,1}\\d\\d\\d[)]{0,1}[\\.-]\\d\\d\\d[\\.-]\\d\\d\\d\\d";  
 
   43     private static final String IP_ADDRESS_REGEX = 
"(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])";  
 
   44     private static final String EMAIL_ADDRESS_REGEX = 
"(?=.{8})[a-z0-9%+_-]+(?:\\.[a-z0-9%+_-]+)*@(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\\.)+[a-z]{2,4}(?<!\\.txt|\\.exe|\\.dll|\\.jpg|\\.xml)";  
 
   45     private static final String URL_REGEX = 
"((((ht|f)tp(s?))\\://)|www\\.)[a-zA-Z0-9\\-\\.]+\\.([a-zA-Z]{2,5})(\\:[0-9]+)*(/($|[a-zA-Z0-9\\.\\,\\;\\?\\'\\\\+&%\\$#\\=~_\\-]+))*";  
 
   46     private static final String CCN_REGEX = 
".*[3456]([ -]?\\d){11,18}.*";  
 
   48     protected String filePath;
 
   49     Map<String, KeywordList> theLists; 
 
   51     PropertyChangeSupport changeSupport;
 
   52     protected List<String> lockedLists;
 
   54     KeywordSearchList(String filePath) {
 
   55         this.filePath = filePath;
 
   56         theLists = 
new LinkedHashMap<>();
 
   57         lockedLists = 
new ArrayList<>();
 
   58         changeSupport = 
new PropertyChangeSupport(
this);
 
   79     void fireLanguagesEvent(LanguagesEvent event) {
 
   81             changeSupport.firePropertyChange(event.toString(), null, null);
 
   82         } 
catch (Exception e) {
 
   83             LOGGER.log(Level.SEVERE, 
"KeywordSearchListsAbstract listener threw exception", e); 
 
   87     public void addPropertyChangeListener(PropertyChangeListener listener) {
 
   88         changeSupport.addPropertyChangeListener(listener);
 
   91     public void removePropertyChangeListener(PropertyChangeListener listener) {
 
   92         changeSupport.removePropertyChangeListener(listener);
 
   95     private void prepopulateLists() {
 
   96         if (!theLists.isEmpty()) {
 
  100         List<Keyword> phones = 
new ArrayList<>();
 
  101         phones.add(
new Keyword(PHONE_NUMBER_REGEX, 
false, BlackboardAttribute.ATTRIBUTE_TYPE.TSK_PHONE_NUMBER));
 
  102         lockedLists.add(
"Phone Numbers");
 
  103         addList(
"Phone Numbers", phones, 
false, 
false, 
true);
 
  106         List<Keyword> ips = 
new ArrayList<>();
 
  107         ips.add(
new Keyword(IP_ADDRESS_REGEX, 
false, BlackboardAttribute.ATTRIBUTE_TYPE.TSK_IP_ADDRESS));
 
  108         lockedLists.add(
"IP Addresses");
 
  109         addList(
"IP Addresses", ips, 
false, 
false, 
true);
 
  112         List<Keyword> emails = 
new ArrayList<>();
 
  113         emails.add(
new Keyword(EMAIL_ADDRESS_REGEX, 
false, BlackboardAttribute.ATTRIBUTE_TYPE.TSK_EMAIL));
 
  114         lockedLists.add(
"Email Addresses");
 
  115         addList(
"Email Addresses", emails, 
true, 
false, 
true);
 
  118         List<Keyword> urls = 
new ArrayList<>();
 
  119         urls.add(
new Keyword(URL_REGEX, 
false, BlackboardAttribute.ATTRIBUTE_TYPE.TSK_URL));
 
  120         lockedLists.add(
"URLs");
 
  121         addList(
"URLs", urls, 
false, 
false, 
true);
 
  124         List<Keyword> ccns = 
new ArrayList<>();
 
  125         ccns.add(
new Keyword(CCN_REGEX, 
false, BlackboardAttribute.ATTRIBUTE_TYPE.TSK_CARD_NUMBER));
 
  126         lockedLists.add(
"Credit Card Numbers");
 
  127         addList(
"Credit Card Numbers", ccns, 
false, 
false, 
true);
 
  133     public void reload() {
 
  134         boolean created = 
false;
 
  142         List<String> toClear = 
new ArrayList<>();
 
  143         for (String list : theLists.keySet()) {
 
  144             if (theLists.get(list).isEditable() == 
false) {
 
  148         for (String clearList : toClear) {
 
  149             theLists.remove(clearList);
 
  152         if (!listFileExists()) {
 
  159         if (!load() && !created) {
 
  165     public List<KeywordList> getListsL() {
 
  166         List<KeywordList> ret = 
new ArrayList<>();
 
  167         for (KeywordList list : theLists.values()) {
 
  173     public List<KeywordList> getListsL(
boolean locked) {
 
  174         List<KeywordList> ret = 
new ArrayList<>();
 
  175         for (KeywordList list : theLists.values()) {
 
  176             if (list.isEditable().equals(locked)) {
 
  188     public List<String> getListNames() {
 
  189         return new ArrayList<>(theLists.keySet());
 
  199     public List<String> getListNames(
boolean locked) {
 
  200         ArrayList<String> lists = 
new ArrayList<>();
 
  201         for (String listName : theLists.keySet()) {
 
  202             KeywordList list = theLists.get(listName);
 
  203             if (locked == list.isEditable()) {
 
  218     public KeywordList getListWithKeyword(String keyword) {
 
  219         KeywordList found = null;
 
  220         for (KeywordList list : theLists.values()) {
 
  221             if (list.hasSearchTerm(keyword)) {
 
  234     int getNumberLists() {
 
  235         return theLists.size();
 
  245     public int getNumberLists(
boolean locked) {
 
  247         for (String listName : theLists.keySet()) {
 
  248             KeywordList list = theLists.get(listName);
 
  249             if (locked == list.isEditable()) {
 
  263     public KeywordList getList(String name) {
 
  264         return theLists.get(name);
 
  274     boolean listExists(String name) {
 
  275         return getList(name) != null;
 
  288     boolean addList(String name, List<Keyword> newList, 
boolean useForIngest, 
boolean ingestMessages, 
boolean locked) {
 
  289         boolean replaced = 
false;
 
  290         KeywordList curList = getList(name);
 
  291         final Date now = 
new Date();
 
  293         if (curList == null) {
 
  294             theLists.put(name, 
new KeywordList(name, now, now, useForIngest, ingestMessages, newList, locked));
 
  296                 changeSupport.firePropertyChange(ListsEvt.LIST_ADDED.toString(), null, name);
 
  297             } 
catch (Exception e) {
 
  298                 LOGGER.log(Level.SEVERE, 
"KeywordSearchListsAbstract listener threw exception", e); 
 
  299                 MessageNotifyUtil.Notify.show(
 
  300                         NbBundle.getMessage(
this.getClass(), 
"KeywordSearchListsAbstract.moduleErr"),
 
  301                         NbBundle.getMessage(
this.getClass(), 
"KeywordSearchListsAbstract.addList.errMsg1.msg"),
 
  302                         MessageNotifyUtil.MessageType.ERROR);
 
  305             theLists.put(name, 
new KeywordList(name, curList.getDateCreated(), now, useForIngest, ingestMessages, newList, locked));
 
  309                 changeSupport.firePropertyChange(ListsEvt.LIST_UPDATED.toString(), null, name);
 
  310             } 
catch (Exception e) {
 
  311                 LOGGER.log(Level.SEVERE, 
"KeywordSearchListsAbstract listener threw exception", e); 
 
  312                 MessageNotifyUtil.Notify.show(
 
  313                         NbBundle.getMessage(
this.getClass(), 
"KeywordSearchListsAbstract.moduleErr"),
 
  314                         NbBundle.getMessage(
this.getClass(), 
"KeywordSearchListsAbstract.addList.errMsg2.msg"),
 
  315                         MessageNotifyUtil.MessageType.ERROR);
 
  322     boolean addList(String name, List<Keyword> newList, 
boolean useForIngest, 
boolean ingestMessages) {
 
  324         boolean isLocked = this.lockedLists.contains(name);
 
  325         return addList(name, newList, useForIngest, ingestMessages, isLocked);
 
  328     boolean addList(String name, List<Keyword> newList) {
 
  329         return addList(name, newList, 
true, 
true);
 
  332     boolean addList(KeywordList list) {
 
  333         return addList(list.getName(), list.getKeywords(), list.getUseForIngest(), list.getIngestMessages(), list.isEditable());
 
  343     boolean saveLists(List<KeywordList> lists) {
 
  344         List<KeywordList> overwritten = 
new ArrayList<>();
 
  345         List<KeywordList> newLists = 
new ArrayList<>();
 
  346         for (KeywordList list : lists) {
 
  347             if (this.listExists(list.getName())) {
 
  348                 overwritten.add(list);
 
  352             theLists.put(list.getName(), list);
 
  354         boolean saved = save(
true);
 
  356             for (KeywordList list : newLists) {
 
  358                     changeSupport.firePropertyChange(ListsEvt.LIST_ADDED.toString(), null, list.getName());
 
  359                 } 
catch (Exception e) {
 
  360                     LOGGER.log(Level.SEVERE, 
"KeywordSearchListsAbstract listener threw exception", e); 
 
  361                     MessageNotifyUtil.Notify.show(
 
  362                             NbBundle.getMessage(
this.getClass(), 
"KeywordSearchListsAbstract.moduleErr"),
 
  363                             NbBundle.getMessage(
this.getClass(), 
"KeywordSearchListsAbstract.saveList.errMsg1.msg"),
 
  364                             MessageNotifyUtil.MessageType.ERROR);
 
  367             for (KeywordList over : overwritten) {
 
  369                     changeSupport.firePropertyChange(ListsEvt.LIST_UPDATED.toString(), null, over.getName());
 
  370                 } 
catch (Exception e) {
 
  371                     LOGGER.log(Level.SEVERE, 
"KeywordSearchListsAbstract listener threw exception", e); 
 
  372                     MessageNotifyUtil.Notify.show(
 
  373                             NbBundle.getMessage(
this.getClass(), 
"KeywordSearchListsAbstract.moduleErr"),
 
  374                             NbBundle.getMessage(
this.getClass(), 
"KeywordSearchListsAbstract.saveList.errMsg2.msg"),
 
  375                             MessageNotifyUtil.MessageType.ERROR);
 
  390     boolean writeLists(List<KeywordList> lists) {
 
  391         List<KeywordList> overwritten = 
new ArrayList<>();
 
  392         List<KeywordList> newLists = 
new ArrayList<>();
 
  393         for (KeywordList list : lists) {
 
  394             if (this.listExists(list.getName())) {
 
  395                 overwritten.add(list);
 
  399             theLists.put(list.getName(), list);
 
  402         for (KeywordList list : newLists) {
 
  405                 changeSupport.firePropertyChange(ListsEvt.LIST_ADDED.toString(), null, list.getName());
 
  406             } 
catch (Exception e) {
 
  407                 LOGGER.log(Level.SEVERE, 
"KeywordSearchListsAbstract listener threw exception", e); 
 
  408                 MessageNotifyUtil.Notify.show(
 
  409                         NbBundle.getMessage(
this.getClass(), 
"KeywordSearchListsAbstract.moduleErr"),
 
  410                         NbBundle.getMessage(
this.getClass(), 
"KeywordSearchListsAbstract.writeLists.errMsg1.msg"),
 
  411                         MessageNotifyUtil.MessageType.ERROR);
 
  415         for (KeywordList over : overwritten) {
 
  418                 changeSupport.firePropertyChange(ListsEvt.LIST_UPDATED.toString(), null, over.getName());
 
  419             } 
catch (Exception e) {
 
  420                 LOGGER.log(Level.SEVERE, 
"KeywordSearchListsAbstract listener threw exception", e); 
 
  421                 MessageNotifyUtil.Notify.show(
 
  422                         NbBundle.getMessage(
this.getClass(), 
"KeywordSearchListsAbstract.moduleErr"),
 
  423                         NbBundle.getMessage(
this.getClass(), 
"KeywordSearchListsAbstract.writeLists.errMsg2.msg"),
 
  424                         MessageNotifyUtil.MessageType.ERROR);
 
  438     boolean deleteList(String name) {
 
  439         KeywordList delList = getList(name);
 
  440         if (delList != null && !delList.isEditable()) {
 
  441             theLists.remove(name);
 
  445             changeSupport.firePropertyChange(ListsEvt.LIST_DELETED.toString(), null, name);
 
  446         } 
catch (Exception e) {
 
  447             LOGGER.log(Level.SEVERE, 
"KeywordSearchListsAbstract listener threw exception", e); 
 
  448             MessageNotifyUtil.Notify.show(
 
  449                     NbBundle.getMessage(
this.getClass(), 
"KeywordSearchListsAbstract.moduleErr"),
 
  450                     NbBundle.getMessage(
this.getClass(), 
"KeywordSearchListsAbstract.deleteList.errMsg1.msg"),
 
  451                     MessageNotifyUtil.MessageType.ERROR);
 
  460     public abstract boolean save();
 
  468     public abstract boolean save(
boolean isExport);
 
  473     public abstract boolean load();
 
  475     private boolean listFileExists() {
 
  476         File f = 
new File(filePath);
 
  477         return f.exists() && f.canRead() && f.canWrite();
 
  480     public void setUseForIngest(String key, 
boolean flag) {
 
  481         theLists.get(key).setUseForIngest(flag);