Reformatted code.

This commit is contained in:
Nick Davis 2014-01-27 16:25:11 -05:00
parent c9d0ace569
commit d6e0366c73
55 changed files with 1791 additions and 1243 deletions

View File

@ -20,6 +20,7 @@
package org.sleuthkit.autopsy.keywordsearch; package org.sleuthkit.autopsy.keywordsearch;
import java.nio.charset.Charset; import java.nio.charset.Charset;
import org.sleuthkit.autopsy.keywordsearch.Ingester.IngesterException; import org.sleuthkit.autopsy.keywordsearch.Ingester.IngesterException;
/** /**
@ -51,7 +52,8 @@ class AbstractFileChunk {
return Server.getChunkIdString(this.parent.getSourceFile().getId(), this.chunkID); return Server.getChunkIdString(this.parent.getSourceFile().getId(), this.chunkID);
} }
public boolean index(Ingester ingester, byte[] content, long contentSize, Charset indexCharset) throws IngesterException { public boolean index(Ingester ingester, byte[] content, long contentSize, Charset indexCharset)
throws IngesterException {
boolean success = true; boolean success = true;
ByteContentStream bcs = new ByteContentStream(content, contentSize, parent.getSourceFile(), indexCharset); ByteContentStream bcs = new ByteContentStream(content, contentSize, parent.getSourceFile(), indexCharset);
try { try {
@ -59,9 +61,11 @@ class AbstractFileChunk {
//logger.log(Level.INFO, "Ingesting string chunk: " + this.getName() + ": " + chunkID); //logger.log(Level.INFO, "Ingesting string chunk: " + this.getName() + ": " + chunkID);
} catch (Exception ingEx) { } catch (Exception ingEx) {
success = false; success = false;
throw new IngesterException("Problem ingesting file string chunk: " + parent.getSourceFile().getId() + ", chunk: " + chunkID, ingEx); throw new IngesterException("Problem ingesting file string chunk: "
+ parent.getSourceFile().getId()
+ ", chunk: " + chunkID, ingEx);
} }
return success; return success;
} }
} }

View File

@ -21,6 +21,7 @@ package org.sleuthkit.autopsy.keywordsearch;
import java.util.Arrays; import java.util.Arrays;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import org.sleuthkit.autopsy.coreutils.StringExtract.StringExtractUnicodeTable.SCRIPT; import org.sleuthkit.autopsy.coreutils.StringExtract.StringExtractUnicodeTable.SCRIPT;
import org.sleuthkit.datamodel.AbstractFile; import org.sleuthkit.datamodel.AbstractFile;
@ -37,44 +38,46 @@ interface AbstractFileExtract {
EXTRACT_UTF16, ///< extract UTF16 text, possible values Boolean.TRUE.toString(), Boolean.FALSE.toString() EXTRACT_UTF16, ///< extract UTF16 text, possible values Boolean.TRUE.toString(), Boolean.FALSE.toString()
EXTRACT_UTF8, ///< extract UTF8 text, possible values Boolean.TRUE.toString(), Boolean.FALSE.toString() EXTRACT_UTF8, ///< extract UTF8 text, possible values Boolean.TRUE.toString(), Boolean.FALSE.toString()
}; }
;
//generally text extractors should ignore archives //generally text extractors should ignore archives
//and let unpacking modules take case of them //and let unpacking modules take case of them
static final List<String> ARCHIVE_MIME_TYPES = static final List<String> ARCHIVE_MIME_TYPES =
Arrays.asList( Arrays.asList(
//ignore unstructured binary and compressed data, for which string extraction or unzipper works better //ignore unstructured binary and compressed data, for which string extraction or unzipper works better
"application/x-7z-compressed", "application/x-7z-compressed",
"application/x-ace-compressed", "application/x-ace-compressed",
"application/x-alz-compressed", "application/x-alz-compressed",
"application/x-arj", "application/x-arj",
"application/vnd.ms-cab-compressed", "application/vnd.ms-cab-compressed",
"application/x-cfs-compressed", "application/x-cfs-compressed",
"application/x-dgc-compressed", "application/x-dgc-compressed",
"application/x-apple-diskimage", "application/x-apple-diskimage",
"application/x-gca-compressed", "application/x-gca-compressed",
"application/x-dar", "application/x-dar",
"application/x-lzx", "application/x-lzx",
"application/x-lzh", "application/x-lzh",
"application/x-rar-compressed", "application/x-rar-compressed",
"application/x-stuffit", "application/x-stuffit",
"application/x-stuffitx", "application/x-stuffitx",
"application/x-gtar", "application/x-gtar",
"application/x-archive", "application/x-archive",
"application/x-executable", "application/x-executable",
"application/x-gzip", "application/x-gzip",
"application/zip", "application/zip",
"application/x-zoo", "application/x-zoo",
"application/x-cpio", "application/x-cpio",
"application/x-shar", "application/x-shar",
"application/x-tar", "application/x-tar",
"application/x-bzip", "application/x-bzip",
"application/x-bzip2", "application/x-bzip2",
"application/x-lzip", "application/x-lzip",
"application/x-lzma", "application/x-lzma",
"application/x-lzop", "application/x-lzop",
"application/x-z", "application/x-z",
"application/x-compress"); "application/x-compress");
/** /**
* Get number of chunks resulted from extracting this AbstractFile * Get number of chunks resulted from extracting this AbstractFile
@ -143,9 +146,9 @@ interface AbstractFileExtract {
* Determines if the file content is supported by the extractor if * Determines if the file content is supported by the extractor if
* isContentTypeSpecific() returns true. * isContentTypeSpecific() returns true.
* *
* @param file to test if its content should be supported * @param file to test if its content should be supported
* @param detectedFormat mime-type with detected format (such as text/plain) * @param detectedFormat mime-type with detected format (such as text/plain)
* or null if not detected * or null if not detected
* @return true if the file content is supported, false otherwise * @return true if the file content is supported, false otherwise
*/ */
boolean isSupported(AbstractFile file, String detectedFormat); boolean isSupported(AbstractFile file, String detectedFormat);

View File

@ -26,6 +26,7 @@ import java.util.Arrays;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.logging.Level; import java.util.logging.Level;
import org.sleuthkit.autopsy.coreutils.Logger; import org.sleuthkit.autopsy.coreutils.Logger;
import org.sleuthkit.autopsy.coreutils.StringExtract.StringExtractUnicodeTable.SCRIPT; import org.sleuthkit.autopsy.coreutils.StringExtract.StringExtractUnicodeTable.SCRIPT;
import org.sleuthkit.autopsy.keywordsearch.Ingester.IngesterException; import org.sleuthkit.autopsy.keywordsearch.Ingester.IngesterException;
@ -37,7 +38,7 @@ import org.sleuthkit.datamodel.ReadContentInputStream;
* divided into chunks and indexed with Solr. If HTML extraction succeeds, * divided into chunks and indexed with Solr. If HTML extraction succeeds,
* chunks are indexed with Solr. * chunks are indexed with Solr.
*/ */
class AbstractFileHtmlExtract implements AbstractFileExtract { class AbstractFileHtmlExtract implements AbstractFileExtract {
private static final Logger logger = Logger.getLogger(AbstractFileHtmlExtract.class.getName()); private static final Logger logger = Logger.getLogger(AbstractFileHtmlExtract.class.getName());
static final Charset outCharset = Server.DEFAULT_INDEXED_TEXT_CHARSET; static final Charset outCharset = Server.DEFAULT_INDEXED_TEXT_CHARSET;
@ -58,7 +59,7 @@ import org.sleuthkit.datamodel.ReadContentInputStream;
"text/html", "text/html",
"text/javascript" //"application/xml", "text/javascript" //"application/xml",
//"application/xml-dtd", //"application/xml-dtd",
); );
private final TikaLanguageIdentifier tikaLanguageIdentifier; private final TikaLanguageIdentifier tikaLanguageIdentifier;
AbstractFileHtmlExtract() { AbstractFileHtmlExtract() {
@ -189,10 +190,12 @@ import org.sleuthkit.datamodel.ReadContentInputStream;
module.checkRunCommitSearch(); module.checkRunCommitSearch();
} }
} catch (IOException ex) { } catch (IOException ex) {
logger.log(Level.WARNING, "Unable to read content stream from " + sourceFile.getId() + ": " + sourceFile.getName(), ex); logger.log(Level.WARNING, "Unable to read content stream from "
+ sourceFile.getId() + ": " + sourceFile.getName(), ex);
success = false; success = false;
} catch (Exception ex) { } catch (Exception ex) {
logger.log(Level.WARNING, "Unexpected error, can't read content stream from " + sourceFile.getId() + ": " + sourceFile.getName(), ex); logger.log(Level.WARNING, "Unexpected error, can't read content stream from "
+ sourceFile.getId() + ": " + sourceFile.getName(), ex);
success = false; success = false;
} finally { } finally {
try { try {

View File

@ -23,6 +23,7 @@ import java.io.InputStream;
import java.io.InputStreamReader; import java.io.InputStreamReader;
import java.io.Reader; import java.io.Reader;
import java.nio.charset.Charset; import java.nio.charset.Charset;
import org.sleuthkit.autopsy.coreutils.Logger; import org.sleuthkit.autopsy.coreutils.Logger;
import org.apache.solr.common.util.ContentStream; import org.apache.solr.common.util.ContentStream;
import org.sleuthkit.datamodel.AbstractContent; import org.sleuthkit.datamodel.AbstractContent;
@ -31,7 +32,7 @@ import org.sleuthkit.datamodel.AbstractFile;
/** /**
* Wrapper over InputStream that implements ContentStream to feed to Solr. * Wrapper over InputStream that implements ContentStream to feed to Solr.
*/ */
class AbstractFileStringContentStream implements ContentStream { class AbstractFileStringContentStream implements ContentStream {
//input //input
private AbstractFile content; private AbstractFile content;
@ -69,7 +70,8 @@ import org.sleuthkit.datamodel.AbstractFile;
@Override @Override
public Long getSize() { public Long getSize() {
//return convertedLength; //return convertedLength;
throw new UnsupportedOperationException("Cannot tell how many chars in converted string, until entire string is converted"); throw new UnsupportedOperationException(
"Cannot tell how many chars in converted string, until entire string is converted");
} }
@Override @Override
@ -85,7 +87,7 @@ import org.sleuthkit.datamodel.AbstractFile;
@Override @Override
protected void finalize() throws Throwable { protected void finalize() throws Throwable {
super.finalize(); super.finalize();
stream.close(); stream.close();
} }
} }

View File

@ -26,6 +26,7 @@ import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.logging.Level; import java.util.logging.Level;
import org.sleuthkit.autopsy.coreutils.Logger; import org.sleuthkit.autopsy.coreutils.Logger;
import org.sleuthkit.autopsy.coreutils.StringExtract.StringExtractUnicodeTable.SCRIPT; import org.sleuthkit.autopsy.coreutils.StringExtract.StringExtractUnicodeTable.SCRIPT;
import org.sleuthkit.autopsy.keywordsearch.Ingester.IngesterException; import org.sleuthkit.autopsy.keywordsearch.Ingester.IngesterException;
@ -51,7 +52,7 @@ class AbstractFileStringExtract implements AbstractFileExtract {
private static final SCRIPT DEFAULT_SCRIPT = SCRIPT.LATIN_2; private static final SCRIPT DEFAULT_SCRIPT = SCRIPT.LATIN_2;
private final List<SCRIPT> extractScripts = new ArrayList<SCRIPT>(); private final List<SCRIPT> extractScripts = new ArrayList<SCRIPT>();
private Map<String, String> extractOptions = new HashMap<String, String>(); private Map<String, String> extractOptions = new HashMap<String, String>();
//disabled prepending of BOM //disabled prepending of BOM
//static { //static {
@ -132,7 +133,8 @@ class AbstractFileStringExtract implements AbstractFileExtract {
//break input stream into chunks //break input stream into chunks
long readSize = 0; long readSize = 0;
while ((readSize = stringStream.read(STRING_CHUNK_BUF, BOM_LEN, (int) MAX_STRING_CHUNK_SIZE - BOM_LEN)) != -1) { while ((readSize = stringStream.read(STRING_CHUNK_BUF, BOM_LEN, (int) MAX_STRING_CHUNK_SIZE - BOM_LEN))
!= -1) {
//FileOutputStream debug = new FileOutputStream("c:\\temp\\" + sourceFile.getName() + Integer.toString(this.numChunks+1)); //FileOutputStream debug = new FileOutputStream("c:\\temp\\" + sourceFile.getName() + Integer.toString(this.numChunks+1));
//debug.write(STRING_CHUNK_BUF, 0, (int)readSize); //debug.write(STRING_CHUNK_BUF, 0, (int)readSize);
@ -143,7 +145,9 @@ class AbstractFileStringExtract implements AbstractFileExtract {
++this.numChunks; ++this.numChunks;
} catch (IngesterException ingEx) { } catch (IngesterException ingEx) {
success = false; success = false;
logger.log(Level.WARNING, "Ingester had a problem with extracted strings from file '" + sourceFile.getName() + "' (id: " + sourceFile.getId() + ").", ingEx); logger.log(Level.WARNING,
"Ingester had a problem with extracted strings from file '" + sourceFile.getName()
+ "' (id: " + sourceFile.getId() + ").", ingEx);
throw ingEx; //need to rethrow/return to signal error and move on throw ingEx; //need to rethrow/return to signal error and move on
} }
@ -159,7 +163,8 @@ class AbstractFileStringExtract implements AbstractFileExtract {
ingester.ingest(this); ingester.ingest(this);
} catch (IOException ex) { } catch (IOException ex) {
logger.log(Level.WARNING, "Unable to read input stream to divide and send to Solr, file: " + sourceFile.getName(), ex); logger.log(Level.WARNING,
"Unable to read input stream to divide and send to Solr, file: " + sourceFile.getName(), ex);
success = false; success = false;
} finally { } finally {
try { try {

View File

@ -22,6 +22,7 @@ import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.nio.charset.Charset; import java.nio.charset.Charset;
import java.util.List; import java.util.List;
import org.sleuthkit.autopsy.coreutils.Logger; import org.sleuthkit.autopsy.coreutils.Logger;
import org.sleuthkit.autopsy.coreutils.StringExtract; import org.sleuthkit.autopsy.coreutils.StringExtract;
import org.sleuthkit.autopsy.coreutils.StringExtract.StringExtractResult; import org.sleuthkit.autopsy.coreutils.StringExtract.StringExtractResult;
@ -33,16 +34,17 @@ import org.sleuthkit.datamodel.TskCoreException;
* Wrapper over StringExtract to provide streaming API Given AbstractFile * Wrapper over StringExtract to provide streaming API Given AbstractFile
* object, extract international strings from the file and read output as a * object, extract international strings from the file and read output as a
* stream of UTF-8 strings as encoded bytes. * stream of UTF-8 strings as encoded bytes.
* * <p/>
* Currently not-thread safe (reusing static buffers for efficiency) * Currently not-thread safe (reusing static buffers for efficiency)
*/ */
class AbstractFileStringIntStream extends InputStream { class AbstractFileStringIntStream extends InputStream {
private AbstractFile content; private AbstractFile content;
private final byte[] oneCharBuf = new byte[1]; private final byte[] oneCharBuf = new byte[1];
private final StringExtract stringExtractor; private final StringExtract stringExtractor;
private static final int FILE_BUF_SIZE = 1024 * 1024; private static final int FILE_BUF_SIZE = 1024 * 1024;
private static final byte[] fileReadBuff = new byte[FILE_BUF_SIZE]; //NOTE: need to run all stream extraction in same thread private static final byte[] fileReadBuff = new byte[FILE_BUF_SIZE];
//NOTE: need to run all stream extraction in same thread
private long fileReadOffset = 0L; private long fileReadOffset = 0L;
private byte[] convertBuff; //stores extracted string encoded as bytes, before returned to user private byte[] convertBuff; //stores extracted string encoded as bytes, before returned to user
private int convertBuffOffset = 0; //offset to start returning data to user on next read() private int convertBuffOffset = 0; //offset to start returning data to user on next read()
@ -59,14 +61,14 @@ import org.sleuthkit.datamodel.TskCoreException;
* strings, then to byte stream, for specified script, auto-detected encoding * strings, then to byte stream, for specified script, auto-detected encoding
* (UTF8, UTF16LE, UTF16BE), and specified output byte stream encoding * (UTF8, UTF16LE, UTF16BE), and specified output byte stream encoding
* *
* @param content input content to process and turn into a stream to convert into strings * @param content input content to process and turn into a stream to convert into strings
* @param scripts a list of scripts to consider * @param scripts a list of scripts to consider
* @param extractUTF8 whether to extract utf8 encoding * @param extractUTF8 whether to extract utf8 encoding
* @param extractUTF16 whether to extract utf16 encoding * @param extractUTF16 whether to extract utf16 encoding
* @param outCharset encoding to use in the output byte stream * @param outCharset encoding to use in the output byte stream
*/ */
public AbstractFileStringIntStream(AbstractFile content, List<SCRIPT> scripts, boolean extractUTF8, public AbstractFileStringIntStream(AbstractFile content, List<SCRIPT> scripts, boolean extractUTF8,
boolean extractUTF16, Charset outCharset) { boolean extractUTF16, Charset outCharset) {
this.content = content; this.content = content;
this.stringExtractor = new StringExtract(); this.stringExtractor = new StringExtract();
this.stringExtractor.setEnabledScripts(scripts); this.stringExtractor.setEnabledScripts(scripts);
@ -100,7 +102,7 @@ import org.sleuthkit.datamodel.TskCoreException;
} else if (len == 0) { } else if (len == 0) {
return 0; return 0;
} }
if (extractUTF8 == false && extractUTF16 == false) { if (extractUTF8 == false && extractUTF16 == false) {
return -1; return -1;
} }
@ -124,22 +126,22 @@ import org.sleuthkit.datamodel.TskCoreException;
//convert more strings, store in buffer //convert more strings, store in buffer
long toRead = 0; long toRead = 0;
//int shiftSize = 0; //int shiftSize = 0;
//if (lastExtractResult != null && lastExtractResult.getTextLength() != 0 //if (lastExtractResult != null && lastExtractResult.getTextLength() != 0
// && (shiftSize = FILE_BUF_SIZE - lastExtractResult.getFirstUnprocessedOff()) > 0) { // && (shiftSize = FILE_BUF_SIZE - lastExtractResult.getFirstUnprocessedOff()) > 0) {
////a string previously extracted ////a string previously extracted
////shift the fileReadBuff past last bytes extracted ////shift the fileReadBuff past last bytes extracted
////read only what's needed to fill the buffer ////read only what's needed to fill the buffer
////to avoid loosing chars and breaking or corrupting potential strings - preserve byte stream continuity ////to avoid loosing chars and breaking or corrupting potential strings - preserve byte stream continuity
//byte[] temp = new byte[shiftSize]; //byte[] temp = new byte[shiftSize];
//System.arraycopy(fileReadBuff, lastExtractResult.getFirstUnprocessedOff(), //System.arraycopy(fileReadBuff, lastExtractResult.getFirstUnprocessedOff(),
// temp, 0, shiftSize); // temp, 0, shiftSize);
//System.arraycopy(temp, 0, fileReadBuff, 0, shiftSize); //System.arraycopy(temp, 0, fileReadBuff, 0, shiftSize);
//toRead = Math.min(lastExtractResult.getFirstUnprocessedOff(), fileSize - fileReadOffset); //toRead = Math.min(lastExtractResult.getFirstUnprocessedOff(), fileSize - fileReadOffset);
//lastExtractResult = null; //lastExtractResult = null;
//} else { //} else {
//fill up entire fileReadBuff fresh //fill up entire fileReadBuff fresh
toRead = Math.min(FILE_BUF_SIZE, fileSize - fileReadOffset); toRead = Math.min(FILE_BUF_SIZE, fileSize - fileReadOffset);
//} //}
int read = content.read(fileReadBuff, fileReadOffset, toRead); int read = content.read(fileReadBuff, fileReadOffset, toRead);
if (read == -1 || read == 0) { if (read == -1 || read == 0) {
@ -173,7 +175,7 @@ import org.sleuthkit.datamodel.TskCoreException;
//return part or all of convert buff to user //return part or all of convert buff to user
final int toCopy = Math.min(convertBuffRemain, len - offsetUser); final int toCopy = Math.min(convertBuffRemain, len - offsetUser);
System.arraycopy(convertBuff, convertBuffOffset, b, offsetUser, toCopy); System.arraycopy(convertBuff, convertBuffOffset, b, offsetUser, toCopy);
//DEBUG //DEBUG
/* /*
if (toCopy > 0) { if (toCopy > 0) {
@ -182,12 +184,12 @@ import org.sleuthkit.datamodel.TskCoreException;
debug.close(); debug.close();
} }
*/ */
convertBuffOffset += toCopy; convertBuffOffset += toCopy;
offsetUser += toCopy; offsetUser += toCopy;
bytesToUser += toCopy; bytesToUser += toCopy;
} }
//if more string data in convertBuff, will be consumed on next read() //if more string data in convertBuff, will be consumed on next read()

View File

@ -21,22 +21,23 @@ package org.sleuthkit.autopsy.keywordsearch;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.nio.charset.Charset; import java.nio.charset.Charset;
import org.sleuthkit.autopsy.coreutils.Logger; import org.sleuthkit.autopsy.coreutils.Logger;
import org.sleuthkit.autopsy.coreutils.StringExtract; import org.sleuthkit.autopsy.coreutils.StringExtract;
import org.sleuthkit.datamodel.AbstractFile; import org.sleuthkit.datamodel.AbstractFile;
import org.sleuthkit.datamodel.TskException; import org.sleuthkit.datamodel.TskException;
/** /**
* AbstractFile input string stream reader/converter - given AbstractFile, * AbstractFile input string stream reader/converter - given AbstractFile,
* extract strings from it and return encoded bytes via read() * extract strings from it and return encoded bytes via read()
* * <p/>
* Note: the utility supports extraction of only LATIN script and UTF8, UTF16LE, UTF16BE encodings * Note: the utility supports extraction of only LATIN script and UTF8, UTF16LE, UTF16BE encodings
* and uses a brute force encoding detection - it's fast but could apply multiple encodings on the same string. * and uses a brute force encoding detection - it's fast but could apply multiple encodings on the same string.
* * <p/>
* For other script/languages support and better encoding detection use AbstractFileStringIntStream streaming class, * For other script/languages support and better encoding detection use AbstractFileStringIntStream streaming class,
* which wraps around StringExtract extractor. * which wraps around StringExtract extractor.
*/ */
class AbstractFileStringStream extends InputStream { class AbstractFileStringStream extends InputStream {
//args //args
private AbstractFile content; private AbstractFile content;
@ -53,7 +54,8 @@ import org.sleuthkit.datamodel.TskException;
private int tempStringLen = 0; private int tempStringLen = 0;
private boolean isEOF = false; private boolean isEOF = false;
private boolean stringAtTempBoundary = false; //if temp has part of string that didn't make it in previous read() private boolean stringAtTempBoundary = false; //if temp has part of string that didn't make it in previous read()
private boolean stringAtBufBoundary = false; //if read buffer has string being processed, continue as string from prev read() in next read() private boolean stringAtBufBoundary = false;
//if read buffer has string being processed, continue as string from prev read() in next read()
private boolean inString = false; //if current temp has min chars required private boolean inString = false; //if current temp has min chars required
private static final byte[] oneCharBuf = new byte[1]; private static final byte[] oneCharBuf = new byte[1];
private final int MIN_PRINTABLE_CHARS = 4; //num. of chars needed to qualify as a char string private final int MIN_PRINTABLE_CHARS = 4; //num. of chars needed to qualify as a char string
@ -63,12 +65,12 @@ import org.sleuthkit.datamodel.TskException;
/** /**
* Construct new string stream from FsContent * Construct new string stream from FsContent
* *
* @param content to extract strings from * @param content to extract strings from
* @param outputCharset target encoding to index as * @param outputCharset target encoding to index as
* @param preserveOnBuffBoundary whether to preserve or split string on a * @param preserveOnBuffBoundary whether to preserve or split string on a
* buffer boundary. If false, will pack into read buffer up to max. * buffer boundary. If false, will pack into read buffer up to max.
* possible, potentially splitting a string. If false, the string will be * possible, potentially splitting a string. If false, the string will be
* preserved for next read. * preserved for next read.
*/ */
public AbstractFileStringStream(AbstractFile content, Charset outputCharset, boolean preserveOnBuffBoundary) { public AbstractFileStringStream(AbstractFile content, Charset outputCharset, boolean preserveOnBuffBoundary) {
this.content = content; this.content = content;
@ -81,7 +83,7 @@ import org.sleuthkit.datamodel.TskException;
* Construct new string stream from FsContent Do not attempt to fill entire * Construct new string stream from FsContent Do not attempt to fill entire
* read buffer if that would break a string * read buffer if that would break a string
* *
* @param content to extract strings from * @param content to extract strings from
* @param outCharset target charset to encode into bytes and index as, e.g. UTF-8 * @param outCharset target charset to encode into bytes and index as, e.g. UTF-8
*/ */
public AbstractFileStringStream(AbstractFile content, Charset outCharset) { public AbstractFileStringStream(AbstractFile content, Charset outCharset) {

View File

@ -34,6 +34,7 @@ import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException; import java.util.concurrent.TimeoutException;
import java.util.logging.Level; import java.util.logging.Level;
import org.sleuthkit.autopsy.coreutils.Logger; import org.sleuthkit.autopsy.coreutils.Logger;
import org.sleuthkit.autopsy.ingest.IngestModuleAbstractFile; import org.sleuthkit.autopsy.ingest.IngestModuleAbstractFile;
import org.sleuthkit.datamodel.AbstractFile; import org.sleuthkit.datamodel.AbstractFile;
@ -55,10 +56,9 @@ import org.sleuthkit.datamodel.TskCoreException;
* divided into chunks and indexed with Solr. Protects against Tika parser hangs * divided into chunks and indexed with Solr. Protects against Tika parser hangs
* (for unexpected/corrupt content) using a timeout mechanism. If Tika * (for unexpected/corrupt content) using a timeout mechanism. If Tika
* extraction succeeds, chunks are indexed with Solr. * extraction succeeds, chunks are indexed with Solr.
* * <p/>
* This Tika extraction/chunking utility is useful for large files of Tika * This Tika extraction/chunking utility is useful for large files of Tika
* parsers-supported content type. * parsers-supported content type.
*
*/ */
class AbstractFileTikaTextExtract implements AbstractFileExtract { class AbstractFileTikaTextExtract implements AbstractFileExtract {
@ -139,13 +139,15 @@ class AbstractFileTikaTextExtract implements AbstractFileExtract {
future.get(Ingester.getTimeout(sourceFile.getSize()), TimeUnit.SECONDS); future.get(Ingester.getTimeout(sourceFile.getSize()), TimeUnit.SECONDS);
} catch (TimeoutException te) { } catch (TimeoutException te) {
tika = null; tika = null;
final String msg = "Exception: Tika parse timeout for content: " + sourceFile.getId() + ", " + sourceFile.getName(); final String msg = "Exception: Tika parse timeout for content: " + sourceFile.getId() + ", "
+ sourceFile.getName();
KeywordSearch.getTikaLogger().log(Level.WARNING, msg, te); KeywordSearch.getTikaLogger().log(Level.WARNING, msg, te);
logger.log(Level.WARNING, msg); logger.log(Level.WARNING, msg);
throw new IngesterException(msg); throw new IngesterException(msg);
} catch (Exception ex) { } catch (Exception ex) {
tika = null; tika = null;
final String msg = "Exception: Unexpected exception from Tika parse task execution for file: " + sourceFile.getId() + ", " + sourceFile.getName(); final String msg = "Exception: Unexpected exception from Tika parse task execution for file: "
+ sourceFile.getId() + ", " + sourceFile.getName();
KeywordSearch.getTikaLogger().log(Level.WARNING, msg, ex); KeywordSearch.getTikaLogger().log(Level.WARNING, msg, ex);
logger.log(Level.WARNING, msg); logger.log(Level.WARNING, msg);
throw new IngesterException(msg); throw new IngesterException(msg);
@ -242,12 +244,14 @@ class AbstractFileTikaTextExtract implements AbstractFileExtract {
module.checkRunCommitSearch(); module.checkRunCommitSearch();
} }
} catch (IOException ex) { } catch (IOException ex) {
final String msg = "Exception: Unable to read Tika content stream from " + sourceFile.getId() + ": " + sourceFile.getName(); final String msg = "Exception: Unable to read Tika content stream from " + sourceFile.getId() + ": "
+ sourceFile.getName();
KeywordSearch.getTikaLogger().log(Level.WARNING, msg, ex); KeywordSearch.getTikaLogger().log(Level.WARNING, msg, ex);
logger.log(Level.WARNING, msg); logger.log(Level.WARNING, msg);
success = false; success = false;
} catch (Exception ex) { } catch (Exception ex) {
final String msg = "Exception: Unexpected error, can't read Tika content stream from " + sourceFile.getId() + ": " + sourceFile.getName(); final String msg = "Exception: Unexpected error, can't read Tika content stream from " + sourceFile.getId()
+ ": " + sourceFile.getName();
KeywordSearch.getTikaLogger().log(Level.WARNING, msg, ex); KeywordSearch.getTikaLogger().log(Level.WARNING, msg, ex);
logger.log(Level.WARNING, msg); logger.log(Level.WARNING, msg);
success = false; success = false;
@ -327,11 +331,15 @@ class AbstractFileTikaTextExtract implements AbstractFileExtract {
try { try {
reader = tika.parse(stream, meta); reader = tika.parse(stream, meta);
} catch (IOException ex) { } catch (IOException ex) {
KeywordSearch.getTikaLogger().log(Level.WARNING, "Exception: Unable to Tika parse the content" + sourceFile.getId() + ": " + sourceFile.getName(), ex); KeywordSearch.getTikaLogger().log(Level.WARNING,
"Exception: Unable to Tika parse the content" + sourceFile.getId()
+ ": " + sourceFile.getName(), ex);
tika = null; tika = null;
reader = null; reader = null;
} catch (Exception ex) { } catch (Exception ex) {
KeywordSearch.getTikaLogger().log(Level.WARNING, "Exception: Unable to Tika parse the content" + sourceFile.getId() + ": " + sourceFile.getName(), ex); KeywordSearch.getTikaLogger().log(Level.WARNING,
"Exception: Unable to Tika parse the content" + sourceFile.getId()
+ ": " + sourceFile.getName(), ex);
tika = null; tika = null;
reader = null; reader = null;
} }

View File

@ -33,7 +33,8 @@ import org.openide.util.NbBundle;
*/ */
abstract class AbstractKeywordSearchPerformer extends javax.swing.JPanel implements KeywordSearchPerformerInterface { abstract class AbstractKeywordSearchPerformer extends javax.swing.JPanel implements KeywordSearchPerformerInterface {
private final String keywordSearchErrorDialogHeader = org.openide.util.NbBundle.getMessage(this.getClass(), "AbstractKeywordSearchPerformer.search.dialogErrorHeader"); private final String keywordSearchErrorDialogHeader = org.openide.util.NbBundle.getMessage(this.getClass(),
"AbstractKeywordSearchPerformer.search.dialogErrorHeader");
protected int filesIndexed; protected int filesIndexed;
AbstractKeywordSearchPerformer() { AbstractKeywordSearchPerformer() {
@ -86,19 +87,26 @@ abstract class AbstractKeywordSearchPerformer extends javax.swing.JPanel impleme
if (filesIndexed == 0) { if (filesIndexed == 0) {
if (isRunning) { if (isRunning) {
KeywordSearchUtil.displayDialog(keywordSearchErrorDialogHeader, NbBundle.getMessage(this.getClass(), KeywordSearchUtil.displayDialog(keywordSearchErrorDialogHeader, NbBundle.getMessage(this.getClass(),
"AbstractKeywordSearchPerformer.search.noFilesInIdxMsg", "AbstractKeywordSearchPerformer.search.noFilesInIdxMsg",
KeywordSearchSettings.getUpdateFrequency().getTime()), KeywordSearchUtil.DIALOG_MESSAGE_TYPE.ERROR); KeywordSearchSettings
.getUpdateFrequency()
.getTime()),
KeywordSearchUtil.DIALOG_MESSAGE_TYPE.ERROR);
} else { } else {
KeywordSearchUtil.displayDialog(keywordSearchErrorDialogHeader, NbBundle.getMessage(this.getClass(), KeywordSearchUtil.displayDialog(keywordSearchErrorDialogHeader, NbBundle.getMessage(this.getClass(),
"AbstractKeywordSearchPerformer.search.noFilesIdxdMsg"), KeywordSearchUtil.DIALOG_MESSAGE_TYPE.ERROR); "AbstractKeywordSearchPerformer.search.noFilesIdxdMsg"),
KeywordSearchUtil.DIALOG_MESSAGE_TYPE.ERROR);
} }
return; return;
} }
//check if keyword search module ingest is running (indexing, etc) //check if keyword search module ingest is running (indexing, etc)
if (isRunning) { if (isRunning) {
if (KeywordSearchUtil.displayConfirmDialog(org.openide.util.NbBundle.getMessage(this.getClass(), "AbstractKeywordSearchPerformer.search.searchIngestInProgressTitle"), if (KeywordSearchUtil.displayConfirmDialog(org.openide.util.NbBundle.getMessage(this.getClass(),
NbBundle.getMessage(this.getClass(), "AbstractKeywordSearchPerformer.search.ingestInProgressBody"), KeywordSearchUtil.DIALOG_MESSAGE_TYPE.WARN) == false) { "AbstractKeywordSearchPerformer.search.searchIngestInProgressTitle"),
NbBundle.getMessage(this.getClass(),
"AbstractKeywordSearchPerformer.search.ingestInProgressBody"),
KeywordSearchUtil.DIALOG_MESSAGE_TYPE.WARN) == false) {
return; return;
} }
} }
@ -108,8 +116,8 @@ abstract class AbstractKeywordSearchPerformer extends javax.swing.JPanel impleme
final List<Keyword> keywords = getQueryList(); final List<Keyword> keywords = getQueryList();
if (keywords.isEmpty()) { if (keywords.isEmpty()) {
KeywordSearchUtil.displayDialog(keywordSearchErrorDialogHeader, NbBundle.getMessage(this.getClass(), KeywordSearchUtil.displayDialog(keywordSearchErrorDialogHeader, NbBundle.getMessage(this.getClass(),
"AbstractKeywordSearchPerformer.search.emptyKeywordErrorBody"), "AbstractKeywordSearchPerformer.search.emptyKeywordErrorBody"),
KeywordSearchUtil.DIALOG_MESSAGE_TYPE.ERROR); KeywordSearchUtil.DIALOG_MESSAGE_TYPE.ERROR);
return; return;
} }
man = new KeywordSearchQueryManager(keywords, Presentation.FLAT); man = new KeywordSearchQueryManager(keywords, Presentation.FLAT);
@ -123,7 +131,8 @@ abstract class AbstractKeywordSearchPerformer extends javax.swing.JPanel impleme
final String queryText = getQueryText(); final String queryText = getQueryText();
if (queryText == null || queryText.trim().equals("")) { if (queryText == null || queryText.trim().equals("")) {
KeywordSearchUtil.displayDialog(keywordSearchErrorDialogHeader, NbBundle.getMessage(this.getClass(), KeywordSearchUtil.displayDialog(keywordSearchErrorDialogHeader, NbBundle.getMessage(this.getClass(),
"AbstractKeywordSearchPerformer.search.pleaseEnterKeywordBody"), KeywordSearchUtil.DIALOG_MESSAGE_TYPE.ERROR); "AbstractKeywordSearchPerformer.search.pleaseEnterKeywordBody"),
KeywordSearchUtil.DIALOG_MESSAGE_TYPE.ERROR);
return; return;
} }
man = new KeywordSearchQueryManager(getQueryText(), queryType, Presentation.FLAT); man = new KeywordSearchQueryManager(getQueryText(), queryType, Presentation.FLAT);
@ -133,7 +142,8 @@ abstract class AbstractKeywordSearchPerformer extends javax.swing.JPanel impleme
man.execute(); man.execute();
} else { } else {
KeywordSearchUtil.displayDialog(keywordSearchErrorDialogHeader, NbBundle.getMessage(this.getClass(), KeywordSearchUtil.displayDialog(keywordSearchErrorDialogHeader, NbBundle.getMessage(this.getClass(),
"AbstractKeywordSearchPerformer.search.invalidSyntaxHeader"), KeywordSearchUtil.DIALOG_MESSAGE_TYPE.ERROR); "AbstractKeywordSearchPerformer.search.invalidSyntaxHeader"),
KeywordSearchUtil.DIALOG_MESSAGE_TYPE.ERROR);
} }
} }
} }

View File

@ -24,6 +24,7 @@ import java.io.InputStream;
import java.io.InputStreamReader; import java.io.InputStreamReader;
import java.io.Reader; import java.io.Reader;
import java.nio.charset.Charset; import java.nio.charset.Charset;
import org.sleuthkit.autopsy.coreutils.Logger; import org.sleuthkit.autopsy.coreutils.Logger;
import org.apache.solr.common.util.ContentStream; import org.apache.solr.common.util.ContentStream;
import org.sleuthkit.datamodel.AbstractContent; import org.sleuthkit.datamodel.AbstractContent;
@ -32,30 +33,30 @@ import org.sleuthkit.datamodel.AbstractContent;
* Stream of bytes representing string with specified encoding * Stream of bytes representing string with specified encoding
* to feed into Solr as ContentStream * to feed into Solr as ContentStream
*/ */
class ByteContentStream implements ContentStream { class ByteContentStream implements ContentStream {
//input //input
private byte[] content; //extracted subcontent private byte[] content; //extracted subcontent
private long contentSize; private long contentSize;
private AbstractContent aContent; //origin private AbstractContent aContent; //origin
private Charset charset; //output byte stream charset of encoded strings private Charset charset; //output byte stream charset of encoded strings
private InputStream stream; private InputStream stream;
private static Logger logger = Logger.getLogger(ByteContentStream.class.getName()); private static Logger logger = Logger.getLogger(ByteContentStream.class.getName());
public ByteContentStream(byte [] content, long contentSize, AbstractContent aContent, Charset charset) { public ByteContentStream(byte[] content, long contentSize, AbstractContent aContent, Charset charset) {
this.content = content; this.content = content;
this.aContent = aContent; this.aContent = aContent;
this.charset = charset; this.charset = charset;
stream = new ByteArrayInputStream(content, 0, (int)contentSize); stream = new ByteArrayInputStream(content, 0, (int) contentSize);
} }
public byte[] getByteContent() { public byte[] getByteContent() {
return content; return content;
} }
public AbstractContent getSourceContent() { public AbstractContent getSourceContent() {
return aContent; return aContent;
} }
@ -95,10 +96,9 @@ class ByteContentStream implements ContentStream {
@Override @Override
protected void finalize() throws Throwable { protected void finalize() throws Throwable {
super.finalize(); super.finalize();
stream.close(); stream.close();
} }
} }

View File

@ -21,6 +21,7 @@ package org.sleuthkit.autopsy.keywordsearch;
import java.util.LinkedHashMap; import java.util.LinkedHashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import org.sleuthkit.datamodel.AbstractFile; import org.sleuthkit.datamodel.AbstractFile;
/** /**
@ -85,8 +86,9 @@ class ContentHit {
/** /**
* Identify the list of files with the first chunk that has a hit * Identify the list of files with the first chunk that has a hit
*
* @param hits * @param hits
* @return * @return
*/ */
static Map<AbstractFile, Integer> flattenResults(List<ContentHit> hits) { static Map<AbstractFile, Integer> flattenResults(List<ContentHit> hits) {
Map<AbstractFile, Integer> ret = new LinkedHashMap<AbstractFile, Integer>(); Map<AbstractFile, Integer> ret = new LinkedHashMap<AbstractFile, Integer>();
@ -99,7 +101,7 @@ class ContentHit {
return ret; return ret;
} }
//flatten results to get unique AbstractFile per hit, with first chunk id encountered //flatten results to get unique AbstractFile per hit, with first chunk id encountered
static LinkedHashMap<AbstractFile, Integer> flattenResults(Map<String, List<ContentHit>> results) { static LinkedHashMap<AbstractFile, Integer> flattenResults(Map<String, List<ContentHit>> results) {
LinkedHashMap<AbstractFile, Integer> flattened = new LinkedHashMap<AbstractFile, Integer>(); LinkedHashMap<AbstractFile, Integer> flattened = new LinkedHashMap<AbstractFile, Integer>();

View File

@ -29,6 +29,7 @@ import java.util.List;
import org.openide.util.NbBundle; import org.openide.util.NbBundle;
import org.sleuthkit.autopsy.coreutils.Logger; import org.sleuthkit.autopsy.coreutils.Logger;
import javax.swing.JMenuItem; import javax.swing.JMenuItem;
import javax.swing.JTextPane; import javax.swing.JTextPane;
import javax.swing.SizeRequirements; import javax.swing.SizeRequirements;
@ -41,6 +42,7 @@ import javax.swing.text.html.ParagraphView;
import javax.swing.text.html.HTMLEditorKit; import javax.swing.text.html.HTMLEditorKit;
import javax.swing.text.html.HTMLEditorKit.HTMLFactory; import javax.swing.text.html.HTMLEditorKit.HTMLFactory;
import javax.swing.text.html.StyleSheet; import javax.swing.text.html.StyleSheet;
import org.netbeans.api.progress.ProgressHandle; import org.netbeans.api.progress.ProgressHandle;
import org.netbeans.api.progress.ProgressHandleFactory; import org.netbeans.api.progress.ProgressHandleFactory;
import org.sleuthkit.autopsy.coreutils.EscapeUtil; import org.sleuthkit.autopsy.coreutils.EscapeUtil;
@ -64,7 +66,7 @@ class ExtractedContentPanel extends javax.swing.JPanel {
} }
private void customizeComponents() { private void customizeComponents() {
HTMLEditorKit editorKit = new HTMLEditorKit() { HTMLEditorKit editorKit = new HTMLEditorKit() {
@Override @Override
public ViewFactory getViewFactory() { public ViewFactory getViewFactory() {
@ -92,7 +94,8 @@ class ExtractedContentPanel extends javax.swing.JPanel {
}; };
} else if (v instanceof ParagraphView) { } else if (v instanceof ParagraphView) {
return new ParagraphView(e) { return new ParagraphView(e) {
protected SizeRequirements calculateMinorAxisRequirements(int axis, SizeRequirements r) { protected SizeRequirements calculateMinorAxisRequirements(int axis,
SizeRequirements r) {
if (r == null) { if (r == null) {
r = new SizeRequirements(); r = new SizeRequirements();
} }
@ -112,12 +115,12 @@ class ExtractedContentPanel extends javax.swing.JPanel {
}; };
} }
}; };
// set font size manually in an effort to get fonts in this panel to look // set font size manually in an effort to get fonts in this panel to look
// similar to what is in the 'String View' content viewer. // similar to what is in the 'String View' content viewer.
StyleSheet ss = editorKit.getStyleSheet(); StyleSheet ss = editorKit.getStyleSheet();
ss.addRule("body {font-size: 8.5px;}"); ss.addRule("body {font-size: 8.5px;}");
extractedTextPane.setEditorKit(editorKit); extractedTextPane.setEditorKit(editorKit);
sourceComboBox.addItemListener(new ItemListener() { sourceComboBox.addItemListener(new ItemListener() {
@ -162,176 +165,239 @@ class ExtractedContentPanel extends javax.swing.JPanel {
copyMenuItem = new javax.swing.JMenuItem(); copyMenuItem = new javax.swing.JMenuItem();
selectAllMenuItem = new javax.swing.JMenuItem(); selectAllMenuItem = new javax.swing.JMenuItem();
jScrollPane1 = new javax.swing.JScrollPane(); jScrollPane1 = new javax.swing.JScrollPane();
extractedTextPane = new JTextPane(){ extractedTextPane = new JTextPane() {
public boolean getScrollableTracksViewportWidth() { public boolean getScrollableTracksViewportWidth() {
return (getSize().width < 400); return (getSize().width < 400);
}}; }
sourceComboBox = new javax.swing.JComboBox(); };
hitLabel = new javax.swing.JLabel(); sourceComboBox = new javax.swing.JComboBox();
hitCountLabel = new javax.swing.JLabel(); hitLabel = new javax.swing.JLabel();
hitOfLabel = new javax.swing.JLabel(); hitCountLabel = new javax.swing.JLabel();
hitTotalLabel = new javax.swing.JLabel(); hitOfLabel = new javax.swing.JLabel();
hitButtonsLabel = new javax.swing.JLabel(); hitTotalLabel = new javax.swing.JLabel();
hitPreviousButton = new javax.swing.JButton(); hitButtonsLabel = new javax.swing.JLabel();
hitNextButton = new javax.swing.JButton(); hitPreviousButton = new javax.swing.JButton();
pageButtonsLabel = new javax.swing.JLabel(); hitNextButton = new javax.swing.JButton();
pagePreviousButton = new javax.swing.JButton(); pageButtonsLabel = new javax.swing.JLabel();
pageNextButton = new javax.swing.JButton(); pagePreviousButton = new javax.swing.JButton();
pagesLabel = new javax.swing.JLabel(); pageNextButton = new javax.swing.JButton();
pageCurLabel = new javax.swing.JLabel(); pagesLabel = new javax.swing.JLabel();
pageOfLabel = new javax.swing.JLabel(); pageCurLabel = new javax.swing.JLabel();
pageTotalLabel = new javax.swing.JLabel(); pageOfLabel = new javax.swing.JLabel();
pageTotalLabel = new javax.swing.JLabel();
copyMenuItem.setText(org.openide.util.NbBundle.getMessage(ExtractedContentPanel.class, "ExtractedContentPanel.copyMenuItem.text")); // NOI18N copyMenuItem.setText(org.openide.util.NbBundle.getMessage(ExtractedContentPanel.class,
rightClickMenu.add(copyMenuItem); "ExtractedContentPanel.copyMenuItem.text")); // NOI18N
rightClickMenu.add(copyMenuItem);
selectAllMenuItem.setText(org.openide.util.NbBundle.getMessage(ExtractedContentPanel.class, "ExtractedContentPanel.selectAllMenuItem.text")); // NOI18N selectAllMenuItem.setText(org.openide.util.NbBundle.getMessage(ExtractedContentPanel.class,
rightClickMenu.add(selectAllMenuItem); "ExtractedContentPanel.selectAllMenuItem.text")); // NOI18N
rightClickMenu.add(selectAllMenuItem);
setPreferredSize(new java.awt.Dimension(700, 400)); setPreferredSize(new java.awt.Dimension(700, 400));
jScrollPane1.setBackground(new java.awt.Color(255, 255, 255)); jScrollPane1.setBackground(new java.awt.Color(255, 255, 255));
jScrollPane1.setPreferredSize(new java.awt.Dimension(700, 400)); jScrollPane1.setPreferredSize(new java.awt.Dimension(700, 400));
extractedTextPane.setEditable(false); extractedTextPane.setEditable(false);
extractedTextPane.setAutoscrolls(false); extractedTextPane.setAutoscrolls(false);
extractedTextPane.setMaximumSize(new java.awt.Dimension(2000, 2000)); extractedTextPane.setMaximumSize(new java.awt.Dimension(2000, 2000));
extractedTextPane.setPreferredSize(new java.awt.Dimension(700, 400)); extractedTextPane.setPreferredSize(new java.awt.Dimension(700, 400));
jScrollPane1.setViewportView(extractedTextPane); jScrollPane1.setViewportView(extractedTextPane);
sourceComboBox.setModel(new javax.swing.DefaultComboBoxModel(new String[] { "Item 1", "Item 2", "Item 3", "Item 4" })); sourceComboBox
.setModel(new javax.swing.DefaultComboBoxModel(new String[]{"Item 1", "Item 2", "Item 3", "Item 4"}));
hitLabel.setText(org.openide.util.NbBundle.getMessage(ExtractedContentPanel.class, "ExtractedContentPanel.hitLabel.text")); // NOI18N hitLabel.setText(org.openide.util.NbBundle.getMessage(ExtractedContentPanel.class,
hitLabel.setToolTipText(org.openide.util.NbBundle.getMessage(ExtractedContentPanel.class, "ExtractedContentPanel.hitLabel.toolTipText")); // NOI18N "ExtractedContentPanel.hitLabel.text")); // NOI18N
hitLabel.setToolTipText(org.openide.util.NbBundle.getMessage(ExtractedContentPanel.class,
"ExtractedContentPanel.hitLabel.toolTipText")); // NOI18N
hitCountLabel.setHorizontalAlignment(javax.swing.SwingConstants.CENTER); hitCountLabel.setHorizontalAlignment(javax.swing.SwingConstants.CENTER);
hitCountLabel.setText(org.openide.util.NbBundle.getMessage(ExtractedContentPanel.class, "ExtractedContentPanel.hitCountLabel.text")); // NOI18N hitCountLabel.setText(org.openide.util.NbBundle.getMessage(ExtractedContentPanel.class,
hitCountLabel.setMaximumSize(new java.awt.Dimension(18, 14)); "ExtractedContentPanel.hitCountLabel.text")); // NOI18N
hitCountLabel.setMinimumSize(new java.awt.Dimension(18, 14)); hitCountLabel.setMaximumSize(new java.awt.Dimension(18, 14));
hitCountLabel.setPreferredSize(new java.awt.Dimension(18, 14)); hitCountLabel.setMinimumSize(new java.awt.Dimension(18, 14));
hitCountLabel.setPreferredSize(new java.awt.Dimension(18, 14));
hitOfLabel.setText(org.openide.util.NbBundle.getMessage(ExtractedContentPanel.class, "ExtractedContentPanel.hitOfLabel.text")); // NOI18N hitOfLabel.setText(org.openide.util.NbBundle.getMessage(ExtractedContentPanel.class,
"ExtractedContentPanel.hitOfLabel.text")); // NOI18N
hitTotalLabel.setHorizontalAlignment(javax.swing.SwingConstants.CENTER); hitTotalLabel.setHorizontalAlignment(javax.swing.SwingConstants.CENTER);
hitTotalLabel.setText(org.openide.util.NbBundle.getMessage(ExtractedContentPanel.class, "ExtractedContentPanel.hitTotalLabel.text")); // NOI18N hitTotalLabel.setText(org.openide.util.NbBundle.getMessage(ExtractedContentPanel.class,
hitTotalLabel.setMaximumSize(new java.awt.Dimension(18, 14)); "ExtractedContentPanel.hitTotalLabel.text")); // NOI18N
hitTotalLabel.setMinimumSize(new java.awt.Dimension(18, 14)); hitTotalLabel.setMaximumSize(new java.awt.Dimension(18, 14));
hitTotalLabel.setPreferredSize(new java.awt.Dimension(18, 14)); hitTotalLabel.setMinimumSize(new java.awt.Dimension(18, 14));
hitTotalLabel.setPreferredSize(new java.awt.Dimension(18, 14));
hitButtonsLabel.setText(org.openide.util.NbBundle.getMessage(ExtractedContentPanel.class, "ExtractedContentPanel.hitButtonsLabel.text")); // NOI18N hitButtonsLabel.setText(org.openide.util.NbBundle.getMessage(ExtractedContentPanel.class,
"ExtractedContentPanel.hitButtonsLabel.text")); // NOI18N
hitPreviousButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/org/sleuthkit/autopsy/keywordsearch/btn_step_back.png"))); // NOI18N hitPreviousButton.setIcon(new javax.swing.ImageIcon(
hitPreviousButton.setText(org.openide.util.NbBundle.getMessage(ExtractedContentPanel.class, "ExtractedContentPanel.hitPreviousButton.text")); // NOI18N getClass().getResource("/org/sleuthkit/autopsy/keywordsearch/btn_step_back.png"))); // NOI18N
hitPreviousButton.setBorder(javax.swing.BorderFactory.createEmptyBorder(1, 1, 1, 1)); hitPreviousButton.setText(org.openide.util.NbBundle.getMessage(ExtractedContentPanel.class,
hitPreviousButton.setBorderPainted(false); "ExtractedContentPanel.hitPreviousButton.text")); // NOI18N
hitPreviousButton.setContentAreaFilled(false); hitPreviousButton.setBorder(javax.swing.BorderFactory.createEmptyBorder(1, 1, 1, 1));
hitPreviousButton.setDisabledIcon(new javax.swing.ImageIcon(getClass().getResource("/org/sleuthkit/autopsy/keywordsearch/btn_step_back_disabled.png"))); // NOI18N hitPreviousButton.setBorderPainted(false);
hitPreviousButton.setMargin(new java.awt.Insets(2, 0, 2, 0)); hitPreviousButton.setContentAreaFilled(false);
hitPreviousButton.setPreferredSize(new java.awt.Dimension(23, 23)); hitPreviousButton.setDisabledIcon(new javax.swing.ImageIcon(
hitPreviousButton.setRolloverIcon(new javax.swing.ImageIcon(getClass().getResource("/org/sleuthkit/autopsy/keywordsearch/btn_step_back_hover.png"))); // NOI18N getClass().getResource("/org/sleuthkit/autopsy/keywordsearch/btn_step_back_disabled.png"))); // NOI18N
hitPreviousButton.setMargin(new java.awt.Insets(2, 0, 2, 0));
hitPreviousButton.setPreferredSize(new java.awt.Dimension(23, 23));
hitPreviousButton.setRolloverIcon(new javax.swing.ImageIcon(
getClass().getResource("/org/sleuthkit/autopsy/keywordsearch/btn_step_back_hover.png"))); // NOI18N
hitNextButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/org/sleuthkit/autopsy/keywordsearch/btn_step_forward.png"))); // NOI18N hitNextButton.setIcon(new javax.swing.ImageIcon(
hitNextButton.setText(org.openide.util.NbBundle.getMessage(ExtractedContentPanel.class, "ExtractedContentPanel.hitNextButton.text")); // NOI18N getClass().getResource("/org/sleuthkit/autopsy/keywordsearch/btn_step_forward.png"))); // NOI18N
hitNextButton.setBorder(javax.swing.BorderFactory.createEmptyBorder(1, 1, 1, 1)); hitNextButton.setText(org.openide.util.NbBundle.getMessage(ExtractedContentPanel.class,
hitNextButton.setBorderPainted(false); "ExtractedContentPanel.hitNextButton.text")); // NOI18N
hitNextButton.setContentAreaFilled(false); hitNextButton.setBorder(javax.swing.BorderFactory.createEmptyBorder(1, 1, 1, 1));
hitNextButton.setDisabledIcon(new javax.swing.ImageIcon(getClass().getResource("/org/sleuthkit/autopsy/keywordsearch/btn_step_forward_disabled.png"))); // NOI18N hitNextButton.setBorderPainted(false);
hitNextButton.setMargin(new java.awt.Insets(2, 0, 2, 0)); hitNextButton.setContentAreaFilled(false);
hitNextButton.setPreferredSize(new java.awt.Dimension(23, 23)); hitNextButton.setDisabledIcon(new javax.swing.ImageIcon(getClass().getResource(
hitNextButton.setRolloverIcon(new javax.swing.ImageIcon(getClass().getResource("/org/sleuthkit/autopsy/keywordsearch/btn_step_forward_hover.png"))); // NOI18N "/org/sleuthkit/autopsy/keywordsearch/btn_step_forward_disabled.png"))); // NOI18N
hitNextButton.setMargin(new java.awt.Insets(2, 0, 2, 0));
hitNextButton.setPreferredSize(new java.awt.Dimension(23, 23));
hitNextButton.setRolloverIcon(new javax.swing.ImageIcon(
getClass().getResource("/org/sleuthkit/autopsy/keywordsearch/btn_step_forward_hover.png"))); // NOI18N
pageButtonsLabel.setText(org.openide.util.NbBundle.getMessage(ExtractedContentPanel.class, "ExtractedContentPanel.pageButtonsLabel.text")); // NOI18N pageButtonsLabel.setText(org.openide.util.NbBundle.getMessage(ExtractedContentPanel.class,
"ExtractedContentPanel.pageButtonsLabel.text")); // NOI18N
pagePreviousButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/org/sleuthkit/autopsy/keywordsearch/btn_step_back.png"))); // NOI18N pagePreviousButton.setIcon(new javax.swing.ImageIcon(
pagePreviousButton.setText(org.openide.util.NbBundle.getMessage(ExtractedContentPanel.class, "ExtractedContentPanel.pagePreviousButton.text")); // NOI18N getClass().getResource("/org/sleuthkit/autopsy/keywordsearch/btn_step_back.png"))); // NOI18N
pagePreviousButton.setActionCommand(org.openide.util.NbBundle.getMessage(ExtractedContentPanel.class, "ExtractedContentPanel.pagePreviousButton.actionCommand")); // NOI18N pagePreviousButton.setText(org.openide.util.NbBundle.getMessage(ExtractedContentPanel.class,
pagePreviousButton.setBorder(javax.swing.BorderFactory.createEmptyBorder(1, 1, 1, 1)); "ExtractedContentPanel.pagePreviousButton.text")); // NOI18N
pagePreviousButton.setBorderPainted(false); pagePreviousButton.setActionCommand(org.openide.util.NbBundle.getMessage(ExtractedContentPanel.class,
pagePreviousButton.setContentAreaFilled(false); "ExtractedContentPanel.pagePreviousButton.actionCommand")); // NOI18N
pagePreviousButton.setDisabledIcon(new javax.swing.ImageIcon(getClass().getResource("/org/sleuthkit/autopsy/keywordsearch/btn_step_back_disabled.png"))); // NOI18N pagePreviousButton.setBorder(javax.swing.BorderFactory.createEmptyBorder(1, 1, 1, 1));
pagePreviousButton.setMargin(new java.awt.Insets(2, 0, 2, 0)); pagePreviousButton.setBorderPainted(false);
pagePreviousButton.setContentAreaFilled(false);
pagePreviousButton.setDisabledIcon(new javax.swing.ImageIcon(
getClass().getResource("/org/sleuthkit/autopsy/keywordsearch/btn_step_back_disabled.png"))); // NOI18N
pagePreviousButton.setMargin(new java.awt.Insets(2, 0, 2, 0));
pageNextButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/org/sleuthkit/autopsy/keywordsearch/btn_step_forward.png"))); // NOI18N pageNextButton.setIcon(new javax.swing.ImageIcon(
pageNextButton.setText(org.openide.util.NbBundle.getMessage(ExtractedContentPanel.class, "ExtractedContentPanel.pageNextButton.text")); // NOI18N getClass().getResource("/org/sleuthkit/autopsy/keywordsearch/btn_step_forward.png"))); // NOI18N
pageNextButton.setBorder(javax.swing.BorderFactory.createEmptyBorder(1, 1, 1, 1)); pageNextButton.setText(org.openide.util.NbBundle.getMessage(ExtractedContentPanel.class,
pageNextButton.setBorderPainted(false); "ExtractedContentPanel.pageNextButton.text")); // NOI18N
pageNextButton.setContentAreaFilled(false); pageNextButton.setBorder(javax.swing.BorderFactory.createEmptyBorder(1, 1, 1, 1));
pageNextButton.setDisabledIcon(new javax.swing.ImageIcon(getClass().getResource("/org/sleuthkit/autopsy/keywordsearch/btn_step_forward_disabled.png"))); // NOI18N pageNextButton.setBorderPainted(false);
pageNextButton.setMargin(new java.awt.Insets(2, 0, 2, 0)); pageNextButton.setContentAreaFilled(false);
pageNextButton.setPreferredSize(new java.awt.Dimension(23, 23)); pageNextButton.setDisabledIcon(new javax.swing.ImageIcon(getClass().getResource(
"/org/sleuthkit/autopsy/keywordsearch/btn_step_forward_disabled.png"))); // NOI18N
pageNextButton.setMargin(new java.awt.Insets(2, 0, 2, 0));
pageNextButton.setPreferredSize(new java.awt.Dimension(23, 23));
pagesLabel.setText(org.openide.util.NbBundle.getMessage(ExtractedContentPanel.class, "ExtractedContentPanel.pagesLabel.text")); // NOI18N pagesLabel.setText(org.openide.util.NbBundle.getMessage(ExtractedContentPanel.class,
"ExtractedContentPanel.pagesLabel.text")); // NOI18N
pageCurLabel.setHorizontalAlignment(javax.swing.SwingConstants.CENTER); pageCurLabel.setHorizontalAlignment(javax.swing.SwingConstants.CENTER);
pageCurLabel.setText(org.openide.util.NbBundle.getMessage(ExtractedContentPanel.class, "ExtractedContentPanel.pageCurLabel.text")); // NOI18N pageCurLabel.setText(org.openide.util.NbBundle.getMessage(ExtractedContentPanel.class,
"ExtractedContentPanel.pageCurLabel.text")); // NOI18N
pageOfLabel.setText(org.openide.util.NbBundle.getMessage(ExtractedContentPanel.class, "ExtractedContentPanel.pageOfLabel.text")); // NOI18N pageOfLabel.setText(org.openide.util.NbBundle.getMessage(ExtractedContentPanel.class,
"ExtractedContentPanel.pageOfLabel.text")); // NOI18N
pageTotalLabel.setHorizontalAlignment(javax.swing.SwingConstants.CENTER); pageTotalLabel.setHorizontalAlignment(javax.swing.SwingConstants.CENTER);
pageTotalLabel.setText(org.openide.util.NbBundle.getMessage(ExtractedContentPanel.class, "ExtractedContentPanel.pageTotalLabel.text")); // NOI18N pageTotalLabel.setText(org.openide.util.NbBundle.getMessage(ExtractedContentPanel.class,
"ExtractedContentPanel.pageTotalLabel.text")); // NOI18N
javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this); javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
this.setLayout(layout); this.setLayout(layout);
layout.setHorizontalGroup( layout.setHorizontalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup() .addGroup(layout.createSequentialGroup()
.addContainerGap() .addContainerGap()
.addComponent(hitLabel) .addComponent(hitLabel)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
.addComponent(hitCountLabel, javax.swing.GroupLayout.PREFERRED_SIZE, 30, javax.swing.GroupLayout.PREFERRED_SIZE) .addComponent(hitCountLabel, javax.swing.GroupLayout.PREFERRED_SIZE, 30,
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) javax.swing.GroupLayout.PREFERRED_SIZE)
.addComponent(hitOfLabel) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) .addComponent(hitOfLabel)
.addComponent(hitTotalLabel, javax.swing.GroupLayout.PREFERRED_SIZE, 30, javax.swing.GroupLayout.PREFERRED_SIZE) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) .addComponent(hitTotalLabel, javax.swing.GroupLayout.PREFERRED_SIZE, 30,
.addComponent(hitButtonsLabel) javax.swing.GroupLayout.PREFERRED_SIZE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
.addComponent(hitPreviousButton, javax.swing.GroupLayout.PREFERRED_SIZE, 23, javax.swing.GroupLayout.PREFERRED_SIZE) .addComponent(hitButtonsLabel)
.addGap(0, 0, 0) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(hitNextButton, javax.swing.GroupLayout.PREFERRED_SIZE, 23, javax.swing.GroupLayout.PREFERRED_SIZE) .addComponent(hitPreviousButton, javax.swing.GroupLayout.PREFERRED_SIZE, 23,
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) javax.swing.GroupLayout.PREFERRED_SIZE)
.addComponent(pagesLabel) .addGap(0, 0, 0)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addComponent(hitNextButton, javax.swing.GroupLayout.PREFERRED_SIZE, 23,
.addComponent(pageCurLabel, javax.swing.GroupLayout.PREFERRED_SIZE, 30, javax.swing.GroupLayout.PREFERRED_SIZE) javax.swing.GroupLayout.PREFERRED_SIZE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
.addComponent(pageOfLabel) .addComponent(pagesLabel)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(pageTotalLabel, javax.swing.GroupLayout.PREFERRED_SIZE, 30, javax.swing.GroupLayout.PREFERRED_SIZE) .addComponent(pageCurLabel, javax.swing.GroupLayout.PREFERRED_SIZE, 30,
.addGap(18, 18, 18) javax.swing.GroupLayout.PREFERRED_SIZE)
.addComponent(pageButtonsLabel) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) .addComponent(pageOfLabel)
.addComponent(pagePreviousButton) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addGap(0, 0, 0) .addComponent(pageTotalLabel, javax.swing.GroupLayout.PREFERRED_SIZE, 30,
.addComponent(pageNextButton, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) javax.swing.GroupLayout.PREFERRED_SIZE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, 71, Short.MAX_VALUE) .addGap(18, 18, 18)
.addComponent(sourceComboBox, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)) .addComponent(pageButtonsLabel)
.addComponent(jScrollPane1, javax.swing.GroupLayout.PREFERRED_SIZE, 0, Short.MAX_VALUE) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
); .addComponent(pagePreviousButton)
layout.setVerticalGroup( .addGap(0, 0, 0)
.addComponent(pageNextButton, javax.swing.GroupLayout.PREFERRED_SIZE,
javax.swing.GroupLayout.DEFAULT_SIZE,
javax.swing.GroupLayout.PREFERRED_SIZE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, 71,
Short.MAX_VALUE)
.addComponent(sourceComboBox, javax.swing.GroupLayout.PREFERRED_SIZE,
javax.swing.GroupLayout.DEFAULT_SIZE,
javax.swing.GroupLayout.PREFERRED_SIZE))
.addComponent(jScrollPane1, javax.swing.GroupLayout.PREFERRED_SIZE, 0, Short.MAX_VALUE)
);
layout.setVerticalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup() .addGroup(layout.createSequentialGroup()
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(sourceComboBox, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) .addComponent(sourceComboBox,
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) javax.swing.GroupLayout.PREFERRED_SIZE,
.addComponent(hitCountLabel, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) javax.swing.GroupLayout.DEFAULT_SIZE,
.addComponent(hitOfLabel) javax.swing.GroupLayout.PREFERRED_SIZE)
.addComponent(hitTotalLabel, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) .addGroup(layout.createParallelGroup(
.addComponent(hitLabel) javax.swing.GroupLayout.Alignment.BASELINE)
.addComponent(hitButtonsLabel)) .addComponent(hitCountLabel,
.addComponent(hitPreviousButton, javax.swing.GroupLayout.PREFERRED_SIZE, 23, javax.swing.GroupLayout.PREFERRED_SIZE) javax.swing.GroupLayout.PREFERRED_SIZE,
.addComponent(hitNextButton, javax.swing.GroupLayout.PREFERRED_SIZE, 23, javax.swing.GroupLayout.PREFERRED_SIZE) javax.swing.GroupLayout.DEFAULT_SIZE,
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) javax.swing.GroupLayout.PREFERRED_SIZE)
.addComponent(pageButtonsLabel) .addComponent(hitOfLabel)
.addComponent(pageTotalLabel) .addComponent(hitTotalLabel,
.addComponent(pagesLabel) javax.swing.GroupLayout.PREFERRED_SIZE,
.addComponent(pageCurLabel) javax.swing.GroupLayout.DEFAULT_SIZE,
.addComponent(pageOfLabel)) javax.swing.GroupLayout.PREFERRED_SIZE)
.addComponent(pageNextButton, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) .addComponent(hitLabel)
.addComponent(pagePreviousButton, javax.swing.GroupLayout.PREFERRED_SIZE, 23, javax.swing.GroupLayout.PREFERRED_SIZE)) .addComponent(hitButtonsLabel))
.addGap(0, 0, 0) .addComponent(hitPreviousButton,
.addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 293, Short.MAX_VALUE)) javax.swing.GroupLayout.PREFERRED_SIZE, 23,
); javax.swing.GroupLayout.PREFERRED_SIZE)
}// </editor-fold>//GEN-END:initComponents .addComponent(hitNextButton,
javax.swing.GroupLayout.PREFERRED_SIZE, 23,
javax.swing.GroupLayout.PREFERRED_SIZE)
.addGroup(layout.createParallelGroup(
javax.swing.GroupLayout.Alignment.BASELINE)
.addComponent(pageButtonsLabel)
.addComponent(pageTotalLabel)
.addComponent(pagesLabel)
.addComponent(pageCurLabel)
.addComponent(pageOfLabel))
.addComponent(pageNextButton,
javax.swing.GroupLayout.PREFERRED_SIZE,
javax.swing.GroupLayout.DEFAULT_SIZE,
javax.swing.GroupLayout.PREFERRED_SIZE)
.addComponent(pagePreviousButton,
javax.swing.GroupLayout.PREFERRED_SIZE, 23,
javax.swing.GroupLayout.PREFERRED_SIZE))
.addGap(0, 0, 0)
.addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 293,
Short.MAX_VALUE))
);
}// </editor-fold>//GEN-END:initComponents
// Variables declaration - do not modify//GEN-BEGIN:variables // Variables declaration - do not modify//GEN-BEGIN:variables
private javax.swing.JMenuItem copyMenuItem; private javax.swing.JMenuItem copyMenuItem;
private javax.swing.JTextPane extractedTextPane; private javax.swing.JTextPane extractedTextPane;
@ -380,9 +446,9 @@ class ExtractedContentPanel extends javax.swing.JPanel {
} }
/** /**
* Return the types of mark up sources that this viewer knows about. * Return the types of mark up sources that this viewer knows about.
* Different sources will markup the text in different ways. * Different sources will markup the text in different ways.
* *
* @return currently available sources on the panel * @return currently available sources on the panel
*/ */
public List<MarkupSource> getSources() { public List<MarkupSource> getSources() {
@ -395,6 +461,7 @@ class ExtractedContentPanel extends javax.swing.JPanel {
/** /**
* Get the source selected in the combo box * Get the source selected in the combo box
*
* @return currently selected Source * @return currently selected Source
*/ */
public MarkupSource getSelectedSource() { public MarkupSource getSelectedSource() {
@ -438,7 +505,6 @@ class ExtractedContentPanel extends javax.swing.JPanel {
} }
/** /**
*
* @param current, current hit to update the display with * @param current, current hit to update the display with
*/ */
void updateCurrentMatchDisplay(int current) { void updateCurrentMatchDisplay(int current) {
@ -450,7 +516,6 @@ class ExtractedContentPanel extends javax.swing.JPanel {
} }
/** /**
*
* @param total total number of hits to update the display with * @param total total number of hits to update the display with
*/ */
void updateTotaMatcheslDisplay(int total) { void updateTotaMatcheslDisplay(int total) {
@ -462,7 +527,6 @@ class ExtractedContentPanel extends javax.swing.JPanel {
} }
/** /**
*
* @param current, current page to update the display with * @param current, current page to update the display with
*/ */
void updateCurrentPageDisplay(int current) { void updateCurrentPageDisplay(int current) {
@ -470,7 +534,6 @@ class ExtractedContentPanel extends javax.swing.JPanel {
} }
/** /**
*
* @param total total number of pages to update the display with * @param total total number of pages to update the display with
*/ */
void updateTotalPageslDisplay(int total) { void updateTotalPageslDisplay(int total) {

View File

@ -78,8 +78,7 @@ public class ExtractedContentViewer implements DataContentViewer {
//for now, do not update second time //for now, do not update second time
if (selectedNode == currentNode) { if (selectedNode == currentNode) {
return; return;
} } else {
else {
currentNode = selectedNode; currentNode = selectedNode;
} }
@ -93,13 +92,13 @@ public class ExtractedContentViewer implements DataContentViewer {
//add additional registered sources for this node //add additional registered sources for this node
sources.addAll(selectedNode.getLookup().lookupAll(MarkupSource.class)); sources.addAll(selectedNode.getLookup().lookupAll(MarkupSource.class));
// if it doesn't have any SOLR content, then we won't add more sources // if it doesn't have any SOLR content, then we won't add more sources
if (solrHasContent(selectedNode) == false) { if (solrHasContent(selectedNode) == false) {
setPanel(sources); setPanel(sources);
return; return;
} }
Content content = selectedNode.getLookup().lookup(Content.class); Content content = selectedNode.getLookup().lookup(Content.class);
if (content == null) { if (content == null) {
return; return;
@ -238,10 +237,10 @@ public class ExtractedContentViewer implements DataContentViewer {
//initialize the source //initialize the source
newSource.getNumberPages(); newSource.getNumberPages();
currentSource = newSource; currentSource = newSource;
sources.add(newSource); sources.add(newSource);
//init pages //init pages
int currentPage = currentSource.getCurrentPage(); int currentPage = currentSource.getCurrentPage();
@ -399,11 +398,11 @@ public class ExtractedContentViewer implements DataContentViewer {
/** /**
* Get extracted content for a node from Solr * Get extracted content for a node from Solr
* *
* @param node a node that has extracted content in Solr (check with * @param node a node that has extracted content in Solr (check with
* solrHasContent(ContentNode)) * solrHasContent(ContentNode))
* @param currentPage currently used page * @param currentPage currently used page
* @param hasChunks true if the content behind the node has multiple chunks. * @param hasChunks true if the content behind the node has multiple chunks.
* This means we need to address the content pages specially. * This means we need to address the content pages specially.
* @return the extracted content * @return the extracted content
* @throws SolrServerException if something goes wrong * @throws SolrServerException if something goes wrong
*/ */
@ -415,24 +414,25 @@ public class ExtractedContentViewer implements DataContentViewer {
int chunkId = 0; int chunkId = 0;
if (hasChunks) { if (hasChunks) {
chunkId = currentPage; chunkId = currentPage;
} } else {
else {
//if no chunks, it is safe to assume there is no text content //if no chunks, it is safe to assume there is no text content
//because we are storing extracted text in chunks only //because we are storing extracted text in chunks only
//and the non-chunk stores meta-data only //and the non-chunk stores meta-data only
String name = contentObj.getName(); String name = contentObj.getName();
String msg = null; String msg = null;
if (contentObj instanceof AbstractFile) { if (contentObj instanceof AbstractFile) {
//we know it's AbstractFile, but do quick check to make sure if we index other objects in future //we know it's AbstractFile, but do quick check to make sure if we index other objects in future
boolean isKnown = FileKnown.KNOWN.equals(((AbstractFile)contentObj).getKnown()); boolean isKnown = FileKnown.KNOWN.equals(((AbstractFile) contentObj).getKnown());
if (isKnown && KeywordSearchSettings.getSkipKnown()) { if (isKnown && KeywordSearchSettings.getSkipKnown()) {
msg = NbBundle.getMessage(this.getClass(), "ExtractedContentViewer.getSolrContent.knownFileMsg", name); msg = NbBundle
.getMessage(this.getClass(), "ExtractedContentViewer.getSolrContent.knownFileMsg", name);
} }
} }
if (msg == null) { if (msg == null) {
msg = NbBundle.getMessage(this.getClass(), "ExtractedContentViewer.getSolrContent.noTxtYetMsg", name); msg = NbBundle.getMessage(this.getClass(), "ExtractedContentViewer.getSolrContent.noTxtYetMsg", name);
} }
String htmlMsg = NbBundle.getMessage(this.getClass(), "ExtractedContentViewer.getSolrContent.txtBodyItal", msg); String htmlMsg = NbBundle
.getMessage(this.getClass(), "ExtractedContentViewer.getSolrContent.txtBodyItal", msg);
return htmlMsg; return htmlMsg;
} }
@ -567,7 +567,7 @@ public class ExtractedContentViewer implements DataContentViewer {
panel.updateControls(null); panel.updateControls(null);
return; return;
} }
if (currentSource.hasNextPage()) { if (currentSource.hasNextPage()) {
currentSource.nextPage(); currentSource.nextPage();
@ -600,7 +600,7 @@ public class ExtractedContentViewer implements DataContentViewer {
panel.updateControls(null); panel.updateControls(null);
return; return;
} }
if (currentSource.hasPreviousPage()) { if (currentSource.hasPreviousPage()) {
currentSource.previousPage(); currentSource.previousPage();

View File

@ -94,7 +94,8 @@ class HighlightedMatchesSource implements MarkupSource, HighlightLookup {
this.hits = hits; this.hits = hits;
} }
HighlightedMatchesSource(Content content, String solrQuery, boolean isRegex, boolean group, Map<String, List<ContentHit>> hits) { HighlightedMatchesSource(Content content, String solrQuery, boolean isRegex, boolean group,
Map<String, List<ContentHit>> hits) {
this(content, solrQuery, isRegex, hits); this(content, solrQuery, isRegex, hits);
this.group = group; this.group = group;
} }
@ -345,11 +346,13 @@ class HighlightedMatchesSource implements MarkupSource, HighlightLookup {
final String filterQuery = Server.Schema.ID.toString() + ":" + contentIdStr; final String filterQuery = Server.Schema.ID.toString() + ":" + contentIdStr;
q.addFilterQuery(filterQuery); q.addFilterQuery(filterQuery);
q.addHighlightField(highLightField); //for exact highlighting, try content_ws field (with stored="true" in Solr schema) q.addHighlightField(
highLightField); //for exact highlighting, try content_ws field (with stored="true" in Solr schema)
//q.setHighlightSimplePre(HIGHLIGHT_PRE); //original highlighter only //q.setHighlightSimplePre(HIGHLIGHT_PRE); //original highlighter only
//q.setHighlightSimplePost(HIGHLIGHT_POST); //original highlighter only //q.setHighlightSimplePost(HIGHLIGHT_POST); //original highlighter only
q.setHighlightFragsize(0); // don't fragment the highlight, works with original highlighter, or needs "single" list builder with FVH q.setHighlightFragsize(
0); // don't fragment the highlight, works with original highlighter, or needs "single" list builder with FVH
//tune the highlighter //tune the highlighter
q.setParam("hl.useFastVectorHighlighter", "on"); //fast highlighter scales better than standard one q.setParam("hl.useFastVectorHighlighter", "on"); //fast highlighter scales better than standard one
@ -439,6 +442,7 @@ class HighlightedMatchesSource implements MarkupSource, HighlightLookup {
return buf.toString(); return buf.toString();
} }
//dummy instance for Lookup only //dummy instance for Lookup only
private static HighlightLookup instance = null; private static HighlightLookup instance = null;

View File

@ -32,6 +32,7 @@ import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException; import java.util.concurrent.TimeoutException;
import java.util.logging.Level; import java.util.logging.Level;
import org.apache.solr.client.solrj.SolrRequest.METHOD; import org.apache.solr.client.solrj.SolrRequest.METHOD;
import org.apache.solr.client.solrj.SolrServerException; import org.apache.solr.client.solrj.SolrServerException;
import org.apache.solr.client.solrj.request.AbstractUpdateRequest; import org.apache.solr.client.solrj.request.AbstractUpdateRequest;
@ -70,10 +71,10 @@ class Ingester {
private final Server solrServer = KeywordSearch.getServer(); private final Server solrServer = KeywordSearch.getServer();
private final GetContentFieldsV getContentFieldsV = new GetContentFieldsV(); private final GetContentFieldsV getContentFieldsV = new GetContentFieldsV();
private static Ingester instance; private static Ingester instance;
//for ingesting chunk as SolrInputDocument (non-content-streaming, by-pass tika) //for ingesting chunk as SolrInputDocument (non-content-streaming, by-pass tika)
//TODO use a streaming way to add content to /update handler //TODO use a streaming way to add content to /update handler
private final static int MAX_DOC_CHUNK_SIZE = 1024*1024; private final static int MAX_DOC_CHUNK_SIZE = 1024 * 1024;
private final byte[] docChunkContentBuf = new byte[MAX_DOC_CHUNK_SIZE]; private final byte[] docChunkContentBuf = new byte[MAX_DOC_CHUNK_SIZE];
private static final String docContentEncoding = "UTF-8"; private static final String docContentEncoding = "UTF-8";
@ -105,7 +106,7 @@ class Ingester {
* *
* @param afscs File AbstractFileStringContentStream to ingest * @param afscs File AbstractFileStringContentStream to ingest
* @throws IngesterException if there was an error processing a specific * @throws IngesterException if there was an error processing a specific
* file, but the Solr server is probably fine. * file, but the Solr server is probably fine.
*/ */
void ingest(AbstractFileStringContentStream afscs) throws IngesterException { void ingest(AbstractFileStringContentStream afscs) throws IngesterException {
Map<String, String> params = getContentFields(afscs.getSourceContent()); Map<String, String> params = getContentFields(afscs.getSourceContent());
@ -121,7 +122,7 @@ class Ingester {
* *
* @param fe AbstractFileExtract to ingest * @param fe AbstractFileExtract to ingest
* @throws IngesterException if there was an error processing a specific * @throws IngesterException if there was an error processing a specific
* file, but the Solr server is probably fine. * file, but the Solr server is probably fine.
*/ */
void ingest(AbstractFileExtract fe) throws IngesterException { void ingest(AbstractFileExtract fe) throws IngesterException {
Map<String, String> params = getContentFields(fe.getSourceFile()); Map<String, String> params = getContentFields(fe.getSourceFile());
@ -136,11 +137,11 @@ class Ingester {
* added to the index. commit() should be called once you're done ingesting * added to the index. commit() should be called once you're done ingesting
* files. AbstractFileChunk represents a file chunk and its chunk content. * files. AbstractFileChunk represents a file chunk and its chunk content.
* *
* @param fec AbstractFileChunk to ingest * @param fec AbstractFileChunk to ingest
* @param size approx. size of the stream in bytes, used for timeout * @param size approx. size of the stream in bytes, used for timeout
* estimation * estimation
* @throws IngesterException if there was an error processing a specific * @throws IngesterException if there was an error processing a specific
* file, but the Solr server is probably fine. * file, but the Solr server is probably fine.
*/ */
void ingest(AbstractFileChunk fec, ByteContentStream bcs, int size) throws IngesterException { void ingest(AbstractFileChunk fec, ByteContentStream bcs, int size) throws IngesterException {
AbstractContent sourceContent = bcs.getSourceContent(); AbstractContent sourceContent = bcs.getSourceContent();
@ -148,7 +149,7 @@ class Ingester {
//overwrite id with the chunk id //overwrite id with the chunk id
params.put(Server.Schema.ID.toString(), params.put(Server.Schema.ID.toString(),
Server.getChunkIdString(sourceContent.getId(), fec.getChunkId())); Server.getChunkIdString(sourceContent.getId(), fec.getChunkId()));
ingest(bcs, params, size); ingest(bcs, params, size);
} }
@ -159,11 +160,11 @@ class Ingester {
* file is a directory or ingestContent is set to false, the file name is * file is a directory or ingestContent is set to false, the file name is
* indexed only. * indexed only.
* *
* @param file File to ingest * @param file File to ingest
* @param ingestContent if true, index the file and the content, otherwise * @param ingestContent if true, index the file and the content, otherwise
* indesx metadata only * indesx metadata only
* @throws IngesterException if there was an error processing a specific * @throws IngesterException if there was an error processing a specific
* file, but the Solr server is probably fine. * file, but the Solr server is probably fine.
*/ */
void ingest(AbstractFile file, boolean ingestContent) throws IngesterException { void ingest(AbstractFile file, boolean ingestContent) throws IngesterException {
if (ingestContent == false || file.isDir()) { if (ingestContent == false || file.isDir()) {
@ -189,11 +190,11 @@ class Ingester {
private class GetContentFieldsV extends ContentVisitor.Default<Map<String, String>> { private class GetContentFieldsV extends ContentVisitor.Default<Map<String, String>> {
private SleuthkitCase curCase = null; private SleuthkitCase curCase = null;
GetContentFieldsV() { GetContentFieldsV() {
curCase = Case.getCurrentCase().getSleuthkitCase(); curCase = Case.getCurrentCase().getSleuthkitCase();
} }
@Override @Override
protected Map<String, String> defaultVisit(Content cntnt) { protected Map<String, String> defaultVisit(Content cntnt) {
return new HashMap<String, String>(); return new HashMap<String, String>();
@ -205,7 +206,7 @@ class Ingester {
getCommonFileContentFields(params, f); getCommonFileContentFields(params, f);
return params; return params;
} }
@Override @Override
public Map<String, String> visit(DerivedFile df) { public Map<String, String> visit(DerivedFile df) {
Map<String, String> params = getCommonFields(df); Map<String, String> params = getCommonFields(df);
@ -225,7 +226,7 @@ class Ingester {
// layout files do not have times // layout files do not have times
return getCommonFields(lf); return getCommonFields(lf);
} }
@Override @Override
public Map<String, String> visit(LocalFile lf) { public Map<String, String> visit(LocalFile lf) {
Map<String, String> params = getCommonFields(lf); Map<String, String> params = getCommonFields(lf);
@ -240,7 +241,7 @@ class Ingester {
params.put(Server.Schema.CRTIME.toString(), ContentUtils.getStringTimeISO8601(file.getCrtime(), file)); params.put(Server.Schema.CRTIME.toString(), ContentUtils.getStringTimeISO8601(file.getCrtime(), file));
return params; return params;
} }
private Map<String, String> getCommonFields(AbstractFile af) { private Map<String, String> getCommonFields(AbstractFile af) {
Map<String, String> params = new HashMap<String, String>(); Map<String, String> params = new HashMap<String, String>();
@ -259,31 +260,31 @@ class Ingester {
} }
} }
/** /**
* Indexing method that bypasses Tika, assumes pure text * Indexing method that bypasses Tika, assumes pure text
* It reads and converts the entire content stream to string, assuming UTF8 * It reads and converts the entire content stream to string, assuming UTF8
* since we can't use streaming approach for Solr /update handler. * since we can't use streaming approach for Solr /update handler.
* This should be safe, since all content is now in max 1MB chunks. * This should be safe, since all content is now in max 1MB chunks.
* * <p/>
* TODO see if can use a byte or string streaming way to add content to /update handler * TODO see if can use a byte or string streaming way to add content to /update handler
* e.g. with XMLUpdateRequestHandler (deprecated in SOlr 4.0.0), see if possible * e.g. with XMLUpdateRequestHandler (deprecated in SOlr 4.0.0), see if possible
* to stream with UpdateRequestHandler * to stream with UpdateRequestHandler
* *
* @param cs * @param cs
* @param fields * @param fields
* @param size * @param size
* @throws org.sleuthkit.autopsy.keywordsearch.Ingester.IngesterException * @throws org.sleuthkit.autopsy.keywordsearch.Ingester.IngesterException
*/ */
private void ingest(ContentStream cs, Map<String, String> fields, final long size) throws IngesterException { private void ingest(ContentStream cs, Map<String, String> fields, final long size) throws IngesterException {
if (fields.get(Server.Schema.IMAGE_ID.toString()) == null) { if (fields.get(Server.Schema.IMAGE_ID.toString()) == null) {
//skip the file, image id unknown //skip the file, image id unknown
String msg = "Skipping indexing the file, unknown image id, for file: " + cs.getName(); String msg = "Skipping indexing the file, unknown image id, for file: " + cs.getName();
logger.log(Level.SEVERE, msg); logger.log(Level.SEVERE, msg);
throw new IngesterException(msg); throw new IngesterException(msg);
} }
SolrInputDocument updateDoc = new SolrInputDocument(); SolrInputDocument updateDoc = new SolrInputDocument();
for (String key : fields.keySet()) { for (String key : fields.keySet()) {
@ -292,9 +293,9 @@ class Ingester {
//using size here, but we are no longer ingesting entire files //using size here, but we are no longer ingesting entire files
//size is normally a chunk size, up to 1MB //size is normally a chunk size, up to 1MB
if (size > 0) { if (size > 0) {
InputStream is = null; InputStream is = null;
int read = 0; int read = 0;
try { try {
@ -306,7 +307,8 @@ class Ingester {
try { try {
is.close(); is.close();
} catch (IOException ex) { } catch (IOException ex) {
logger.log(Level.WARNING, "Could not close input stream after reading content, " + cs.getName(), ex); logger.log(Level.WARNING, "Could not close input stream after reading content, " + cs.getName(),
ex);
} }
} }
@ -321,12 +323,11 @@ class Ingester {
} else { } else {
updateDoc.addField(Server.Schema.CONTENT.toString(), ""); updateDoc.addField(Server.Schema.CONTENT.toString(), "");
} }
} } else {
else {
//no content, such as case when 0th chunk indexed //no content, such as case when 0th chunk indexed
updateDoc.addField(Server.Schema.CONTENT.toString(), ""); updateDoc.addField(Server.Schema.CONTENT.toString(), "");
} }
try { try {
//TODO consider timeout thread, or vary socket timeout based on size of indexed content //TODO consider timeout thread, or vary socket timeout based on size of indexed content
@ -343,13 +344,12 @@ class Ingester {
* Delegate method actually performing the indexing work for objects * Delegate method actually performing the indexing work for objects
* implementing ContentStream * implementing ContentStream
* *
* @param cs ContentStream to ingest * @param cs ContentStream to ingest
* @param fields content specific fields * @param fields content specific fields
* @param size size of the content - used to determine the Solr timeout, not * @param size size of the content - used to determine the Solr timeout, not
* used to populate meta-data * used to populate meta-data
*
* @throws IngesterException if there was an error processing a specific * @throws IngesterException if there was an error processing a specific
* content, but the Solr server is probably fine. * content, but the Solr server is probably fine.
*/ */
private void ingestExtract(ContentStream cs, Map<String, String> fields, final long size) throws IngesterException { private void ingestExtract(ContentStream cs, Map<String, String> fields, final long size) throws IngesterException {
final ContentStreamUpdateRequest up = new ContentStreamUpdateRequest("/update/extract"); final ContentStreamUpdateRequest up = new ContentStreamUpdateRequest("/update/extract");
@ -373,9 +373,12 @@ class Ingester {
logger.log(Level.WARNING, "Solr timeout encountered, trying to restart Solr"); logger.log(Level.WARNING, "Solr timeout encountered, trying to restart Solr");
//restart may be needed to recover from some error conditions //restart may be needed to recover from some error conditions
hardSolrRestart(); hardSolrRestart();
throw new IngesterException("Solr index request time out for id: " + fields.get("id") + ", name: " + fields.get("file_name")); throw new IngesterException(
"Solr index request time out for id: " + fields.get("id") + ", name: " + fields.get("file_name"));
} catch (Exception e) { } catch (Exception e) {
throw new IngesterException("Problem posting content to Solr, id: " + fields.get("id") + ", name: " + fields.get("file_name"), e); throw new IngesterException(
"Problem posting content to Solr, id: " + fields.get("id") + ", name: " + fields.get("file_name"),
e);
} }
uncommitedIngests = true; uncommitedIngests = true;
} }
@ -458,7 +461,8 @@ class Ingester {
// When Tika has problems with a document, it throws a server error // When Tika has problems with a document, it throws a server error
// but it's okay to continue with other documents // but it's okay to continue with other documents
if (ec.equals(ErrorCode.SERVER_ERROR)) { if (ec.equals(ErrorCode.SERVER_ERROR)) {
throw new RuntimeException("Problem posting file contents to Solr. SolrException error code: " + ec, ex); throw new RuntimeException("Problem posting file contents to Solr. SolrException error code: " + ec,
ex);
} else { } else {
// shouldn't get any other error codes // shouldn't get any other error codes
throw ex; throw ex;
@ -486,7 +490,7 @@ class Ingester {
/** /**
* Helper to set document fields * Helper to set document fields
* *
* @param up request with document * @param up request with document
* @param fields map of field-names->values * @param fields map of field-names->values
*/ */
private static void setFields(ContentStreamUpdateRequest up, Map<String, String> fields) { private static void setFields(ContentStreamUpdateRequest up, Map<String, String> fields) {

View File

@ -19,6 +19,7 @@
package org.sleuthkit.autopsy.keywordsearch; package org.sleuthkit.autopsy.keywordsearch;
import java.util.logging.Level; import java.util.logging.Level;
import org.openide.modules.ModuleInstall; import org.openide.modules.ModuleInstall;
import org.openide.util.NbBundle; import org.openide.util.NbBundle;
import org.openide.windows.WindowManager; import org.openide.windows.WindowManager;
@ -31,7 +32,7 @@ import org.sleuthkit.autopsy.coreutils.Version;
/** /**
* Starts up the Solr server when the module is loaded, and stops it when the * Starts up the Solr server when the module is loaded, and stops it when the
* application is closed. * application is closed.
* * <p/>
* In addition, the default KeywordSearch config files (NSRL, Options, Scripts) * In addition, the default KeywordSearch config files (NSRL, Options, Scripts)
* are generated here, if they config files do not already exist. * are generated here, if they config files do not already exist.
*/ */
@ -202,7 +203,9 @@ class Installer extends ModuleInstall {
WindowManager.getDefault().invokeWhenUIReady(new Runnable() { WindowManager.getDefault().invokeWhenUIReady(new Runnable() {
@Override @Override
public void run() { public void run() {
final String msg = NbBundle.getMessage(this.getClass(), "Installer.reportPortError", curFailPort, Version.getName(), Server.PROPERTIES_CURRENT_SERVER_PORT, Server.PROPERTIES_FILE); final String msg = NbBundle
.getMessage(this.getClass(), "Installer.reportPortError", curFailPort, Version.getName(),
Server.PROPERTIES_CURRENT_SERVER_PORT, Server.PROPERTIES_FILE);
MessageNotifyUtil.Notify.error(NbBundle.getMessage(this.getClass(), "Installer.errorInitKsmMsg"), msg); MessageNotifyUtil.Notify.error(NbBundle.getMessage(this.getClass(), "Installer.errorInitKsmMsg"), msg);
} }
}); });
@ -212,7 +215,8 @@ class Installer extends ModuleInstall {
WindowManager.getDefault().invokeWhenUIReady(new Runnable() { WindowManager.getDefault().invokeWhenUIReady(new Runnable() {
@Override @Override
public void run() { public void run() {
final String msg = NbBundle.getMessage(this.getClass(), "Installer.reportStopPortError", curFailPort, Server.PROPERTIES_CURRENT_STOP_PORT, Server.PROPERTIES_FILE); final String msg = NbBundle.getMessage(this.getClass(), "Installer.reportStopPortError", curFailPort,
Server.PROPERTIES_CURRENT_STOP_PORT, Server.PROPERTIES_FILE);
MessageNotifyUtil.Notify.error(NbBundle.getMessage(this.getClass(), "Installer.errorInitKsmMsg"), msg); MessageNotifyUtil.Notify.error(NbBundle.getMessage(this.getClass(), "Installer.errorInitKsmMsg"), msg);
} }
}); });
@ -222,7 +226,10 @@ class Installer extends ModuleInstall {
WindowManager.getDefault().invokeWhenUIReady(new Runnable() { WindowManager.getDefault().invokeWhenUIReady(new Runnable() {
@Override @Override
public void run() { public void run() {
final String msg = NbBundle.getMessage(this.getClass(), "Installer.reportInitError", KeywordSearch.getServer().getCurrentSolrServerPort(), Version.getName(), Server.PROPERTIES_CURRENT_SERVER_PORT, Server.PROPERTIES_FILE); final String msg = NbBundle.getMessage(this.getClass(), "Installer.reportInitError",
KeywordSearch.getServer().getCurrentSolrServerPort(),
Version.getName(), Server.PROPERTIES_CURRENT_SERVER_PORT,
Server.PROPERTIES_FILE);
MessageNotifyUtil.Notify.error(NbBundle.getMessage(this.getClass(), "Installer.errorInitKsmMsg"), msg); MessageNotifyUtil.Notify.error(NbBundle.getMessage(this.getClass(), "Installer.errorInitKsmMsg"), msg);
MessageNotifyUtil.Notify.error(NbBundle.getMessage(this.getClass(), "Installer.errorInitKsmMsg"), msg); MessageNotifyUtil.Notify.error(NbBundle.getMessage(this.getClass(), "Installer.errorInitKsmMsg"), msg);

View File

@ -24,6 +24,7 @@ import java.io.Reader;
import java.io.StringReader; import java.io.StringReader;
import java.util.List; import java.util.List;
import java.util.logging.Level; import java.util.logging.Level;
import org.sleuthkit.autopsy.coreutils.Logger; import org.sleuthkit.autopsy.coreutils.Logger;
import net.htmlparser.jericho.Attributes; import net.htmlparser.jericho.Attributes;
import net.htmlparser.jericho.Renderer; import net.htmlparser.jericho.Renderer;
@ -38,34 +39,35 @@ import net.htmlparser.jericho.StartTagType;
*/ */
class JerichoParserWrapper { class JerichoParserWrapper {
private static final Logger logger = Logger.getLogger(JerichoParserWrapper.class.getName()); private static final Logger logger = Logger.getLogger(JerichoParserWrapper.class.getName());
private InputStream in; private InputStream in;
private StringBuilder out; private StringBuilder out;
private Reader reader; private Reader reader;
JerichoParserWrapper(InputStream in) { JerichoParserWrapper(InputStream in) {
this.in = in; this.in = in;
} }
/** /**
* Returns the reader, initialized in parse(), which will be * Returns the reader, initialized in parse(), which will be
* null if parse() is not called or if parse() throws an error. * null if parse() is not called or if parse() throws an error.
*
* @return Reader * @return Reader
*/ */
public Reader getReader() { public Reader getReader() {
return reader; return reader;
} }
/** /**
* Initialize the reader by parsing the InputStream, adding it to StringBuilder, * Initialize the reader by parsing the InputStream, adding it to StringBuilder,
* and creating a StringReader from it. * and creating a StringReader from it.
*/ */
public void parse() { public void parse() {
out = new StringBuilder(); out = new StringBuilder();
try { try {
Source source = new Source(in); Source source = new Source(in);
source.fullSequentialParse(); source.fullSequentialParse();
String text; String text;
StringBuilder scripts = new StringBuilder(); StringBuilder scripts = new StringBuilder();
StringBuilder links = new StringBuilder(); StringBuilder links = new StringBuilder();
@ -77,37 +79,37 @@ class JerichoParserWrapper {
int numImages = 1; int numImages = 1;
int numComments = 1; int numComments = 1;
int numOthers = 1; int numOthers = 1;
text = renderHTMLAsPlainText(source); text = renderHTMLAsPlainText(source);
// Get all the tags in the source // Get all the tags in the source
List<StartTag> tags = source.getAllStartTags(); List<StartTag> tags = source.getAllStartTags();
for(StartTag tag : tags) { for (StartTag tag : tags) {
if(tag.getName().equals("script")) { if (tag.getName().equals("script")) {
// If the <script> tag has attributes // If the <script> tag has attributes
scripts.append(numScripts).append(") "); scripts.append(numScripts).append(") ");
if(tag.getTagContent().length()>0) { if (tag.getTagContent().length() > 0) {
scripts.append(tag.getTagContent()).append(" "); scripts.append(tag.getTagContent()).append(" ");
} }
// Get whats between the <script> .. </script> tags // Get whats between the <script> .. </script> tags
scripts.append(tag.getElement().getContent()).append("\n"); scripts.append(tag.getElement().getContent()).append("\n");
numScripts++; numScripts++;
} else if(tag.getName().equals("a")) { } else if (tag.getName().equals("a")) {
links.append(numLinks).append(") "); links.append(numLinks).append(") ");
links.append(tag.getTagContent()).append("\n"); links.append(tag.getTagContent()).append("\n");
numLinks++; numLinks++;
} else if(tag.getName().equals("img")) { } else if (tag.getName().equals("img")) {
images.append(numImages).append(") "); images.append(numImages).append(") ");
images.append(tag.getTagContent()).append("\n"); images.append(tag.getTagContent()).append("\n");
numImages++; numImages++;
} else if(tag.getTagType().equals(StartTagType.COMMENT)) { } else if (tag.getTagType().equals(StartTagType.COMMENT)) {
comments.append(numComments).append(") "); comments.append(numComments).append(") ");
comments.append(tag.getTagContent()).append("\n"); comments.append(tag.getTagContent()).append("\n");
numComments++; numComments++;
} else { } else {
// Make sure it has an attribute // Make sure it has an attribute
Attributes atts = tag.getAttributes(); Attributes atts = tag.getAttributes();
if (atts!=null && atts.length()>0) { if (atts != null && atts.length() > 0) {
others.append(numOthers).append(") "); others.append(numOthers).append(") ");
others.append(tag.getName()).append(":"); others.append(tag.getName()).append(":");
others.append(tag.getTagContent()).append("\n"); others.append(tag.getTagContent()).append("\n");
@ -119,19 +121,23 @@ class JerichoParserWrapper {
out.append(text).append("\n\n"); out.append(text).append("\n\n");
out.append("----------NONVISIBLE TEXT----------\n\n"); out.append("----------NONVISIBLE TEXT----------\n\n");
if(numScripts>1) { if (numScripts > 1) {
out.append("---Scripts---\n"); out.append("---Scripts---\n");
out.append(scripts.toString()).append("\n"); out.append(scripts.toString()).append("\n");
} if(numLinks>1) { }
if (numLinks > 1) {
out.append("---Links---\n"); out.append("---Links---\n");
out.append(links.toString()).append("\n"); out.append(links.toString()).append("\n");
} if(numImages>1) { }
if (numImages > 1) {
out.append("---Images---\n"); out.append("---Images---\n");
out.append(images.toString()).append("\n"); out.append(images.toString()).append("\n");
} if(numComments>1) { }
if (numComments > 1) {
out.append("---Comments---\n"); out.append("---Comments---\n");
out.append(comments.toString()).append("\n"); out.append(comments.toString()).append("\n");
} if(numOthers>1) { }
if (numOthers > 1) {
out.append("---Others---\n"); out.append("---Others---\n");
out.append(others.toString()).append("\n"); out.append(others.toString()).append("\n");
} }
@ -141,7 +147,7 @@ class JerichoParserWrapper {
logger.log(Level.WARNING, "Unable to parse the HTML file", ex); logger.log(Level.WARNING, "Unable to parse the HTML file", ex);
} }
} }
// Extract text from the source, nicely formatted with whitespace and // Extract text from the source, nicely formatted with whitespace and
// newlines where appropriate. // newlines where appropriate.
private String renderHTMLAsPlainText(Source source) { private String renderHTMLAsPlainText(Source source) {

View File

@ -30,36 +30,33 @@ class Keyword {
private BlackboardAttribute.ATTRIBUTE_TYPE keywordType = null; private BlackboardAttribute.ATTRIBUTE_TYPE keywordType = null;
/** /**
* * @param query Keyword to search for
* @param query Keyword to search for
* @param isLiteral false if reg exp * @param isLiteral false if reg exp
*/ */
Keyword(String query, boolean isLiteral) { Keyword(String query, boolean isLiteral) {
this.keywordString = query; this.keywordString = query;
this.isLiteral = isLiteral; this.isLiteral = isLiteral;
} }
/** /**
* * @param query Keyword to search for
* @param query Keyword to search for * @param isLiteral false if reg exp
* @param isLiteral false if reg exp * @param keywordType
* @param keywordType
*/ */
Keyword(String query, boolean isLiteral, BlackboardAttribute.ATTRIBUTE_TYPE keywordType) { Keyword(String query, boolean isLiteral, BlackboardAttribute.ATTRIBUTE_TYPE keywordType) {
this(query, isLiteral); this(query, isLiteral);
this.keywordType = keywordType; this.keywordType = keywordType;
} }
void setType(BlackboardAttribute.ATTRIBUTE_TYPE keywordType) { void setType(BlackboardAttribute.ATTRIBUTE_TYPE keywordType) {
this.keywordType = keywordType; this.keywordType = keywordType;
} }
BlackboardAttribute.ATTRIBUTE_TYPE getType() { BlackboardAttribute.ATTRIBUTE_TYPE getType() {
return this.keywordType; return this.keywordType;
} }
/** /**
*
* @return Keyword to search for * @return Keyword to search for
*/ */
String getQuery() { String getQuery() {
@ -72,10 +69,10 @@ class Keyword {
@Override @Override
public String toString() { public String toString() {
return "Keyword{" + "query=" + keywordString + ", isLiteral=" + isLiteral + ", keywordType=" + keywordType + '}'; return "Keyword{" + "query=" + keywordString + ", isLiteral=" + isLiteral + ", keywordType=" + keywordType
+ '}';
} }
@Override @Override
public boolean equals(Object obj) { public boolean equals(Object obj) {
@ -86,7 +83,8 @@ class Keyword {
return false; return false;
} }
final Keyword other = (Keyword) obj; final Keyword other = (Keyword) obj;
if ((this.keywordString == null) ? (other.keywordString != null) : !this.keywordString.equals(other.keywordString)) { if ((this.keywordString == null) ? (other.keywordString != null)
: !this.keywordString.equals(other.keywordString)) {
return false; return false;
} }
if (this.isLiteral != other.isLiteral) { if (this.isLiteral != other.isLiteral) {

View File

@ -23,7 +23,6 @@ import java.util.Iterator;
import java.util.Set; import java.util.Set;
/** /**
*
* Filter to restrict query only specific files, chunks, images * Filter to restrict query only specific files, chunks, images
* Single filter supports multiple ids per file/chunk/image, that act as OR filter * Single filter supports multiple ids per file/chunk/image, that act as OR filter
*/ */
@ -33,7 +32,7 @@ class KeywordQueryFilter {
FILE, CHUNK, DATA_SOURCE FILE, CHUNK, DATA_SOURCE
}; };
private Set<Long>idFilters; private Set<Long> idFilters;
private FilterType filterType; private FilterType filterType;
public KeywordQueryFilter(FilterType filterType, long id) { public KeywordQueryFilter(FilterType filterType, long id) {
@ -42,7 +41,7 @@ class KeywordQueryFilter {
this.idFilters.add(id); this.idFilters.add(id);
} }
public KeywordQueryFilter(FilterType filterType, Set<Long>ids) { public KeywordQueryFilter(FilterType filterType, Set<Long> ids) {
this.filterType = filterType; this.filterType = filterType;
this.idFilters = ids; this.idFilters = ids;
} }
@ -59,8 +58,8 @@ class KeywordQueryFilter {
public String toString() { public String toString() {
StringBuilder sb = new StringBuilder(); StringBuilder sb = new StringBuilder();
String id = null; String id = null;
Iterator<Long>it = idFilters.iterator(); Iterator<Long> it = idFilters.iterator();
for (int i = 0; it.hasNext(); ++i) { for (int i = 0; it.hasNext(); ++i) {
if (i > 0) { if (i > 0) {
sb.append(" "); //OR sb.append(" "); //OR

View File

@ -27,6 +27,7 @@ import java.util.logging.FileHandler;
import java.util.logging.Level; import java.util.logging.Level;
import java.util.logging.Logger; import java.util.logging.Logger;
import java.util.logging.SimpleFormatter; import java.util.logging.SimpleFormatter;
import org.openide.util.Exceptions; import org.openide.util.Exceptions;
import org.sleuthkit.autopsy.casemodule.Case; import org.sleuthkit.autopsy.casemodule.Case;
import org.sleuthkit.autopsy.coreutils.PlatformUtil; import org.sleuthkit.autopsy.coreutils.PlatformUtil;
@ -66,7 +67,8 @@ class KeywordSearch {
static { static {
try { try {
final int MAX_TIKA_LOG_FILES = 3; final int MAX_TIKA_LOG_FILES = 3;
FileHandler tikaLogHandler = new FileHandler(PlatformUtil.getUserDirectory().getAbsolutePath() + "/var/log/tika.log", FileHandler tikaLogHandler = new FileHandler(
PlatformUtil.getUserDirectory().getAbsolutePath() + "/var/log/tika.log",
0, MAX_TIKA_LOG_FILES); 0, MAX_TIKA_LOG_FILES);
tikaLogHandler.setFormatter(new SimpleFormatter()); tikaLogHandler.setFormatter(new SimpleFormatter());
tikaLogHandler.setEncoding(PlatformUtil.getLogFileEncoding()); tikaLogHandler.setEncoding(PlatformUtil.getLogFileEncoding());
@ -88,16 +90,16 @@ class KeywordSearch {
static Logger getTikaLogger() { static Logger getTikaLogger() {
return TIKA_LOGGER; return TIKA_LOGGER;
} }
public static void addNumIndexedFilesChangeListener(PropertyChangeListener l) { public static void addNumIndexedFilesChangeListener(PropertyChangeListener l) {
changeSupport.addPropertyChangeListener(NUM_FILES_CHANGE_EVT, l); changeSupport.addPropertyChangeListener(NUM_FILES_CHANGE_EVT, l);
} }
public static void removeNumIndexedFilesChangeListener(PropertyChangeListener l) { public static void removeNumIndexedFilesChangeListener(PropertyChangeListener l) {
changeSupport.removePropertyChangeListener(l); changeSupport.removePropertyChangeListener(l);
} }
static void fireNumIndexedFilesChange(Integer oldNum, Integer newNum) { static void fireNumIndexedFilesChange(Integer oldNum, Integer newNum) {
changeSupport.firePropertyChange(NUM_FILES_CHANGE_EVT, oldNum, newNum); changeSupport.firePropertyChange(NUM_FILES_CHANGE_EVT, oldNum, newNum);
} }

View File

@ -21,6 +21,7 @@ package org.sleuthkit.autopsy.keywordsearch;
import java.awt.Component; import java.awt.Component;
import java.awt.event.ActionEvent; import java.awt.event.ActionEvent;
import javax.swing.AbstractAction; import javax.swing.AbstractAction;
import org.openide.util.actions.Presenter; import org.openide.util.actions.Presenter;
final class KeywordSearchAction extends AbstractAction implements Presenter.Toolbar { final class KeywordSearchAction extends AbstractAction implements Presenter.Toolbar {

View File

@ -23,6 +23,7 @@ import java.awt.event.ActionListener;
import java.awt.event.WindowAdapter; import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent; import java.awt.event.WindowEvent;
import java.awt.event.WindowListener; import java.awt.event.WindowListener;
import org.openide.util.HelpCtx; import org.openide.util.HelpCtx;
import org.openide.util.actions.CallableSystemAction; import org.openide.util.actions.CallableSystemAction;
import org.sleuthkit.autopsy.corecomponents.AdvancedConfigurationDialog; import org.sleuthkit.autopsy.corecomponents.AdvancedConfigurationDialog;
@ -30,9 +31,10 @@ import org.sleuthkit.autopsy.corecomponents.AdvancedConfigurationDialog;
/** /**
* System action to open the KeywordSearch Options panel. * System action to open the KeywordSearch Options panel.
*/ */
class KeywordSearchConfigurationAction extends CallableSystemAction{ class KeywordSearchConfigurationAction extends CallableSystemAction {
private static final String ACTION_NAME = org.openide.util.NbBundle.getMessage(KeywordSearchPanel.class, "ListBundleConfig"); private static final String ACTION_NAME = org.openide.util.NbBundle
.getMessage(KeywordSearchPanel.class, "ListBundleConfig");
private KeywordSearchConfigurationPanel panel; private KeywordSearchConfigurationPanel panel;
@Override @Override
@ -59,9 +61,9 @@ class KeywordSearchConfigurationAction extends CallableSystemAction{
dialog.addWindowListener(exitListener); dialog.addWindowListener(exitListener);
dialog.display(panel); dialog.display(panel);
} }
private KeywordSearchConfigurationPanel getPanel() { private KeywordSearchConfigurationPanel getPanel() {
if(panel==null) { if (panel == null) {
panel = new KeywordSearchConfigurationPanel(); panel = new KeywordSearchConfigurationPanel();
} }
return panel; return panel;
@ -76,7 +78,7 @@ class KeywordSearchConfigurationAction extends CallableSystemAction{
public HelpCtx getHelpCtx() { public HelpCtx getHelpCtx() {
return HelpCtx.DEFAULT_HELP; return HelpCtx.DEFAULT_HELP;
} }
@Override @Override
protected boolean asynchronous() { protected boolean asynchronous() {
return false; return false;

View File

@ -35,18 +35,30 @@ final class KeywordSearchConfigurationPanel extends javax.swing.JPanel implement
initComponents(); initComponents();
customizeComponents(); customizeComponents();
} }
private void customizeComponents() { private void customizeComponents() {
setName(NbBundle.getMessage(this.getClass(), "KeywordSearchConfigurationPanel.customizeComponents.title")); setName(NbBundle.getMessage(this.getClass(), "KeywordSearchConfigurationPanel.customizeComponents.title"));
listsPanel = new KeywordSearchConfigurationPanel1(); listsPanel = new KeywordSearchConfigurationPanel1();
languagesPanel = new KeywordSearchConfigurationPanel3(); languagesPanel = new KeywordSearchConfigurationPanel3();
generalPanel = new KeywordSearchConfigurationPanel2(); generalPanel = new KeywordSearchConfigurationPanel2();
tabbedPane.insertTab(NbBundle.getMessage(this.getClass(), "KeywordSearchConfigurationPanel.customizeComponents.listTabTitle"), null, tabbedPane.insertTab(NbBundle.getMessage(this.getClass(),
listsPanel, NbBundle.getMessage(this.getClass(), "KeywordSearchConfigurationPanel.customizeComponents.listLabToolTip"), 0); "KeywordSearchConfigurationPanel.customizeComponents.listTabTitle"),
tabbedPane.insertTab(NbBundle.getMessage(this.getClass(), "KeywordSearchConfigurationPanel.customizeComponents.stringExtTitle"), null, null,
languagesPanel, NbBundle.getMessage(this.getClass(), "KeywordSearchConfigurationPanel.customizeComponents.stringExtToolTip"), 1); listsPanel, NbBundle.getMessage(this.getClass(),
tabbedPane.insertTab(NbBundle.getMessage(this.getClass(), "KeywordSearchConfigurationPanel.customizeComponents.genTabTitle"), null, "KeywordSearchConfigurationPanel.customizeComponents.listLabToolTip"),
generalPanel, NbBundle.getMessage(this.getClass(), "KeywordSearchConfigurationPanel.customizeComponents.genTabToolTip"), 2); 0);
tabbedPane.insertTab(NbBundle.getMessage(this.getClass(),
"KeywordSearchConfigurationPanel.customizeComponents.stringExtTitle"),
null,
languagesPanel, NbBundle.getMessage(this.getClass(),
"KeywordSearchConfigurationPanel.customizeComponents.stringExtToolTip"),
1);
tabbedPane.insertTab(
NbBundle.getMessage(this.getClass(), "KeywordSearchConfigurationPanel.customizeComponents.genTabTitle"),
null,
generalPanel, NbBundle.getMessage(this.getClass(),
"KeywordSearchConfigurationPanel.customizeComponents.genTabToolTip"),
2);
} }
/** /**
@ -62,12 +74,14 @@ final class KeywordSearchConfigurationPanel extends javax.swing.JPanel implement
javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this); javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
this.setLayout(layout); this.setLayout(layout);
layout.setHorizontalGroup( layout.setHorizontalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(tabbedPane, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.DEFAULT_SIZE, 675, Short.MAX_VALUE) .addComponent(tabbedPane, javax.swing.GroupLayout.Alignment.TRAILING,
javax.swing.GroupLayout.DEFAULT_SIZE, 675, Short.MAX_VALUE)
); );
layout.setVerticalGroup( layout.setVerticalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(tabbedPane, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.DEFAULT_SIZE, 505, Short.MAX_VALUE) .addComponent(tabbedPane, javax.swing.GroupLayout.Alignment.TRAILING,
javax.swing.GroupLayout.DEFAULT_SIZE, 505, Short.MAX_VALUE)
); );
}// </editor-fold>//GEN-END:initComponents }// </editor-fold>//GEN-END:initComponents
@ -95,14 +109,14 @@ final class KeywordSearchConfigurationPanel extends javax.swing.JPanel implement
} }
public void cancel() { public void cancel() {
KeywordSearchListsXML.getCurrent().reload(); KeywordSearchListsXML.getCurrent().reload();
} }
boolean valid() { boolean valid() {
// TODO check whether form is consistent and complete // TODO check whether form is consistent and complete
return true; return true;
} }
// Variables declaration - do not modify//GEN-BEGIN:variables // Variables declaration - do not modify//GEN-BEGIN:variables
private javax.swing.JTabbedPane tabbedPane; private javax.swing.JTabbedPane tabbedPane;
// End of variables declaration//GEN-END:variables // End of variables declaration//GEN-END:variables

View File

@ -41,11 +41,14 @@ class KeywordSearchConfigurationPanel1 extends javax.swing.JPanel implements Opt
KeywordSearchListsManagementPanel listsManagementPanel; KeywordSearchListsManagementPanel listsManagementPanel;
KeywordSearchEditListPanel editListPanel; KeywordSearchEditListPanel editListPanel;
private static final Logger logger = Logger.getLogger(KeywordSearchConfigurationPanel1.class.getName()); private static final Logger logger = Logger.getLogger(KeywordSearchConfigurationPanel1.class.getName());
private static final String KEYWORD_CONFIG_NAME = org.openide.util.NbBundle.getMessage(KeywordSearchPanel.class, "ListBundleConfig"); private static final String KEYWORD_CONFIG_NAME = org.openide.util.NbBundle.getMessage(KeywordSearchPanel.class,
"ListBundleConfig");
/** Creates new form KeywordSearchConfigurationPanel1 */
/**
* Creates new form KeywordSearchConfigurationPanel1
*/
KeywordSearchConfigurationPanel1() { KeywordSearchConfigurationPanel1() {
initComponents(); initComponents();
customizeComponents(); customizeComponents();
setName(KEYWORD_CONFIG_NAME); setName(KEYWORD_CONFIG_NAME);
@ -57,12 +60,14 @@ class KeywordSearchConfigurationPanel1 extends javax.swing.JPanel implements Opt
listsManagementPanel.addListSelectionListener(editListPanel); listsManagementPanel.addListSelectionListener(editListPanel);
editListPanel.addDeleteButtonActionPerformed(new ActionListener() { editListPanel.addDeleteButtonActionPerformed(new ActionListener() {
@Override @Override
public void actionPerformed(ActionEvent e) { public void actionPerformed(ActionEvent e) {
if (KeywordSearchUtil.displayConfirmDialog(NbBundle.getMessage(this.getClass(), "KeywordSearchConfigurationPanel1.customizeComponents.title") if (KeywordSearchUtil.displayConfirmDialog(NbBundle.getMessage(this.getClass(),
, NbBundle.getMessage(this.getClass(), "KeywordSearchConfigurationPanel1.customizeComponents.body" ) "KeywordSearchConfigurationPanel1.customizeComponents.title")
, KeywordSearchUtil.DIALOG_MESSAGE_TYPE.WARN) ) { , NbBundle.getMessage(this.getClass(),
"KeywordSearchConfigurationPanel1.customizeComponents.body")
, KeywordSearchUtil.DIALOG_MESSAGE_TYPE.WARN)) {
KeywordSearchListsXML deleter = KeywordSearchListsXML.getCurrent(); KeywordSearchListsXML deleter = KeywordSearchListsXML.getCurrent();
String toDelete = editListPanel.getCurrentKeywordList().getName(); String toDelete = editListPanel.getCurrentKeywordList().getName();
@ -73,9 +78,9 @@ class KeywordSearchConfigurationPanel1 extends javax.swing.JPanel implements Opt
} }
} }
}); });
editListPanel.addSaveButtonActionPerformed(new ActionListener() { editListPanel.addSaveButtonActionPerformed(new ActionListener() {
@Override @Override
public void actionPerformed(ActionEvent e) { public void actionPerformed(ActionEvent e) {
final String FEATURE_NAME = "Save Keyword List"; final String FEATURE_NAME = "Save Keyword List";
@ -84,8 +89,9 @@ class KeywordSearchConfigurationPanel1 extends javax.swing.JPanel implements Opt
List<Keyword> keywords = currentKeywordList.getKeywords(); List<Keyword> keywords = currentKeywordList.getKeywords();
if (keywords.isEmpty()) { if (keywords.isEmpty()) {
KeywordSearchUtil.displayDialog(FEATURE_NAME, NbBundle.getMessage(this.getClass(), "KeywordSearchConfigurationPanel1.customizeComponents.keywordListEmptyErr"), KeywordSearchUtil.displayDialog(FEATURE_NAME, NbBundle.getMessage(this.getClass(),
KeywordSearchUtil.DIALOG_MESSAGE_TYPE.INFO); "KeywordSearchConfigurationPanel1.customizeComponents.keywordListEmptyErr"),
KeywordSearchUtil.DIALOG_MESSAGE_TYPE.INFO);
return; return;
} }
@ -102,13 +108,18 @@ class KeywordSearchConfigurationPanel1 extends javax.swing.JPanel implements Opt
} }
if (writer.listExists(listName) && writer.getList(listName).isLocked()) { if (writer.listExists(listName) && writer.getList(listName).isLocked()) {
KeywordSearchUtil.displayDialog(FEATURE_NAME, NbBundle.getMessage(this.getClass(), "KeywordSearchConfigurationPanel1.customizeComponents.noOwDefaultMsg"), KeywordSearchUtil.DIALOG_MESSAGE_TYPE.WARN); KeywordSearchUtil.displayDialog(FEATURE_NAME, NbBundle.getMessage(this.getClass(),
"KeywordSearchConfigurationPanel1.customizeComponents.noOwDefaultMsg"),
KeywordSearchUtil.DIALOG_MESSAGE_TYPE.WARN);
return; return;
} }
boolean shouldAdd = false; boolean shouldAdd = false;
if (writer.listExists(listName)) { if (writer.listExists(listName)) {
boolean replace = KeywordSearchUtil.displayConfirmDialog(FEATURE_NAME, NbBundle.getMessage(this.getClass(), "KeywordSearchConfigurationPanel1.customizeComponents.kwListExistMsg", listName), boolean replace = KeywordSearchUtil.displayConfirmDialog(FEATURE_NAME,
KeywordSearchUtil.DIALOG_MESSAGE_TYPE.WARN); NbBundle.getMessage(this.getClass(),
"KeywordSearchConfigurationPanel1.customizeComponents.kwListExistMsg",
listName),
KeywordSearchUtil.DIALOG_MESSAGE_TYPE.WARN);
if (replace) { if (replace) {
shouldAdd = true; shouldAdd = true;
} }
@ -119,34 +130,38 @@ class KeywordSearchConfigurationPanel1 extends javax.swing.JPanel implements Opt
if (shouldAdd) { if (shouldAdd) {
writer.addList(listName, keywords); writer.addList(listName, keywords);
KeywordSearchUtil.displayDialog(FEATURE_NAME, NbBundle.getMessage(this.getClass(), "KeywordSearchConfigurationPanel1.customizeComponents.kwListSavedMsg", listName), KeywordSearchUtil.DIALOG_MESSAGE_TYPE.INFO); KeywordSearchUtil.displayDialog(FEATURE_NAME, NbBundle.getMessage(this.getClass(),
"KeywordSearchConfigurationPanel1.customizeComponents.kwListSavedMsg",
listName),
KeywordSearchUtil.DIALOG_MESSAGE_TYPE.INFO);
} }
//currentKeywordList = writer.getList(listName); //currentKeywordList = writer.getList(listName);
listsManagementPanel.resync(); listsManagementPanel.resync();
} }
}); });
mainSplitPane.setLeftComponent(listsManagementPanel); mainSplitPane.setLeftComponent(listsManagementPanel);
mainSplitPane.setRightComponent(editListPanel); mainSplitPane.setRightComponent(editListPanel);
mainSplitPane.revalidate(); mainSplitPane.revalidate();
mainSplitPane.repaint(); mainSplitPane.repaint();
} }
@Override @Override
public void store() { public void store() {
KeywordSearchListsXML.getCurrent().save(false); KeywordSearchListsXML.getCurrent().save(false);
//refresh the list viewer/searcher panel //refresh the list viewer/searcher panel
KeywordSearchListsViewerPanel.getDefault().resync(); KeywordSearchListsViewerPanel.getDefault().resync();
} }
@Override @Override
public void load() { public void load() {
listsManagementPanel.load(); listsManagementPanel.load();
} }
/** This method is called from within the constructor to /**
* This method is called from within the constructor to
* initialize the form. * initialize the form.
* WARNING: Do NOT modify this code. The content of this method is * WARNING: Do NOT modify this code. The content of this method is
* always regenerated by the Form Editor. * always regenerated by the Form Editor.
@ -165,12 +180,12 @@ class KeywordSearchConfigurationPanel1 extends javax.swing.JPanel implements Opt
javax.swing.GroupLayout leftPanelLayout = new javax.swing.GroupLayout(leftPanel); javax.swing.GroupLayout leftPanelLayout = new javax.swing.GroupLayout(leftPanel);
leftPanel.setLayout(leftPanelLayout); leftPanel.setLayout(leftPanelLayout);
leftPanelLayout.setHorizontalGroup( leftPanelLayout.setHorizontalGroup(
leftPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) leftPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGap(0, 275, Short.MAX_VALUE) .addGap(0, 275, Short.MAX_VALUE)
); );
leftPanelLayout.setVerticalGroup( leftPanelLayout.setVerticalGroup(
leftPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) leftPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGap(0, 327, Short.MAX_VALUE) .addGap(0, 327, Short.MAX_VALUE)
); );
mainSplitPane.setLeftComponent(leftPanel); mainSplitPane.setLeftComponent(leftPanel);
@ -178,12 +193,12 @@ class KeywordSearchConfigurationPanel1 extends javax.swing.JPanel implements Opt
javax.swing.GroupLayout rightPanelLayout = new javax.swing.GroupLayout(rightPanel); javax.swing.GroupLayout rightPanelLayout = new javax.swing.GroupLayout(rightPanel);
rightPanel.setLayout(rightPanelLayout); rightPanel.setLayout(rightPanelLayout);
rightPanelLayout.setHorizontalGroup( rightPanelLayout.setHorizontalGroup(
rightPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) rightPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGap(0, 318, Short.MAX_VALUE) .addGap(0, 318, Short.MAX_VALUE)
); );
rightPanelLayout.setVerticalGroup( rightPanelLayout.setVerticalGroup(
rightPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) rightPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGap(0, 327, Short.MAX_VALUE) .addGap(0, 327, Short.MAX_VALUE)
); );
mainSplitPane.setRightComponent(rightPanel); mainSplitPane.setRightComponent(rightPanel);
@ -191,12 +206,12 @@ class KeywordSearchConfigurationPanel1 extends javax.swing.JPanel implements Opt
javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this); javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
this.setLayout(layout); this.setLayout(layout);
layout.setHorizontalGroup( layout.setHorizontalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(mainSplitPane) .addComponent(mainSplitPane)
); );
layout.setVerticalGroup( layout.setVerticalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(mainSplitPane) .addComponent(mainSplitPane)
); );
}// </editor-fold>//GEN-END:initComponents }// </editor-fold>//GEN-END:initComponents
@ -205,5 +220,5 @@ class KeywordSearchConfigurationPanel1 extends javax.swing.JPanel implements Opt
private javax.swing.JSplitPane mainSplitPane; private javax.swing.JSplitPane mainSplitPane;
private javax.swing.JPanel rightPanel; private javax.swing.JPanel rightPanel;
// End of variables declaration//GEN-END:variables // End of variables declaration//GEN-END:variables
} }

View File

@ -21,6 +21,7 @@ package org.sleuthkit.autopsy.keywordsearch;
import java.beans.PropertyChangeEvent; import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener; import java.beans.PropertyChangeListener;
import java.util.logging.Level; import java.util.logging.Level;
import org.sleuthkit.autopsy.coreutils.Logger; import org.sleuthkit.autopsy.coreutils.Logger;
import org.apache.solr.client.solrj.SolrServerException; import org.apache.solr.client.solrj.SolrServerException;
import org.sleuthkit.autopsy.corecomponents.OptionsPanel; import org.sleuthkit.autopsy.corecomponents.OptionsPanel;
@ -97,35 +98,52 @@ class KeywordSearchConfigurationPanel2 extends javax.swing.JPanel implements Opt
timeRadioButton3 = new javax.swing.JRadioButton(); timeRadioButton3 = new javax.swing.JRadioButton();
timeRadioButton4 = new javax.swing.JRadioButton(); timeRadioButton4 = new javax.swing.JRadioButton();
skipNSRLCheckBox.setText(org.openide.util.NbBundle.getMessage(KeywordSearchConfigurationPanel2.class, "KeywordSearchConfigurationPanel2.skipNSRLCheckBox.text")); // NOI18N skipNSRLCheckBox.setText(org.openide.util.NbBundle.getMessage(KeywordSearchConfigurationPanel2.class,
skipNSRLCheckBox.setToolTipText(org.openide.util.NbBundle.getMessage(KeywordSearchConfigurationPanel2.class, "KeywordSearchConfigurationPanel2.skipNSRLCheckBox.toolTipText")); // NOI18N "KeywordSearchConfigurationPanel2.skipNSRLCheckBox.text")); // NOI18N
skipNSRLCheckBox.setToolTipText(org.openide.util.NbBundle.getMessage(KeywordSearchConfigurationPanel2.class,
"KeywordSearchConfigurationPanel2.skipNSRLCheckBox.toolTipText")); // NOI18N
filesIndexedLabel.setText(org.openide.util.NbBundle.getMessage(KeywordSearchConfigurationPanel2.class, "KeywordSearchConfigurationPanel2.filesIndexedLabel.text")); // NOI18N filesIndexedLabel.setText(org.openide.util.NbBundle.getMessage(KeywordSearchConfigurationPanel2.class,
"KeywordSearchConfigurationPanel2.filesIndexedLabel.text")); // NOI18N
filesIndexedValue.setText(org.openide.util.NbBundle.getMessage(KeywordSearchConfigurationPanel2.class, "KeywordSearchConfigurationPanel2.filesIndexedValue.text")); // NOI18N filesIndexedValue.setText(org.openide.util.NbBundle.getMessage(KeywordSearchConfigurationPanel2.class,
"KeywordSearchConfigurationPanel2.filesIndexedValue.text")); // NOI18N
filesIndexedValue.setMaximumSize(null); filesIndexedValue.setMaximumSize(null);
chunksLabel.setText(org.openide.util.NbBundle.getMessage(KeywordSearchConfigurationPanel2.class, "KeywordSearchConfigurationPanel2.chunksLabel.text")); // NOI18N chunksLabel.setText(org.openide.util.NbBundle.getMessage(KeywordSearchConfigurationPanel2.class,
"KeywordSearchConfigurationPanel2.chunksLabel.text")); // NOI18N
chunksValLabel.setText(org.openide.util.NbBundle.getMessage(KeywordSearchConfigurationPanel2.class, "KeywordSearchConfigurationPanel2.chunksValLabel.text")); // NOI18N chunksValLabel.setText(org.openide.util.NbBundle.getMessage(KeywordSearchConfigurationPanel2.class,
"KeywordSearchConfigurationPanel2.chunksValLabel.text")); // NOI18N
settingsLabel.setText(org.openide.util.NbBundle.getMessage(KeywordSearchConfigurationPanel2.class, "KeywordSearchConfigurationPanel2.settingsLabel.text")); // NOI18N settingsLabel.setText(org.openide.util.NbBundle.getMessage(KeywordSearchConfigurationPanel2.class,
"KeywordSearchConfigurationPanel2.settingsLabel.text")); // NOI18N
informationLabel.setText(org.openide.util.NbBundle.getMessage(KeywordSearchConfigurationPanel2.class, "KeywordSearchConfigurationPanel2.informationLabel.text")); // NOI18N informationLabel.setText(org.openide.util.NbBundle.getMessage(KeywordSearchConfigurationPanel2.class,
"KeywordSearchConfigurationPanel2.informationLabel.text")); // NOI18N
frequencyLabel.setText(org.openide.util.NbBundle.getMessage(KeywordSearchConfigurationPanel2.class, "KeywordSearchConfigurationPanel2.frequencyLabel.text")); // NOI18N frequencyLabel.setText(org.openide.util.NbBundle.getMessage(KeywordSearchConfigurationPanel2.class,
"KeywordSearchConfigurationPanel2.frequencyLabel.text")); // NOI18N
timeRadioButton1.setText(org.openide.util.NbBundle.getMessage(KeywordSearchConfigurationPanel2.class, "KeywordSearchConfigurationPanel2.timeRadioButton1.text")); // NOI18N timeRadioButton1.setText(org.openide.util.NbBundle.getMessage(KeywordSearchConfigurationPanel2.class,
timeRadioButton1.setToolTipText(org.openide.util.NbBundle.getMessage(KeywordSearchConfigurationPanel2.class, "KeywordSearchConfigurationPanel2.timeRadioButton1.toolTipText")); // NOI18N "KeywordSearchConfigurationPanel2.timeRadioButton1.text")); // NOI18N
timeRadioButton1.setToolTipText(org.openide.util.NbBundle.getMessage(KeywordSearchConfigurationPanel2.class,
"KeywordSearchConfigurationPanel2.timeRadioButton1.toolTipText")); // NOI18N
timeRadioButton2.setText(org.openide.util.NbBundle.getMessage(KeywordSearchConfigurationPanel2.class, "KeywordSearchConfigurationPanel2.timeRadioButton2.text")); // NOI18N timeRadioButton2.setText(org.openide.util.NbBundle.getMessage(KeywordSearchConfigurationPanel2.class,
timeRadioButton2.setToolTipText(org.openide.util.NbBundle.getMessage(KeywordSearchConfigurationPanel2.class, "KeywordSearchConfigurationPanel2.timeRadioButton2.toolTipText")); // NOI18N "KeywordSearchConfigurationPanel2.timeRadioButton2.text")); // NOI18N
timeRadioButton2.setToolTipText(org.openide.util.NbBundle.getMessage(KeywordSearchConfigurationPanel2.class,
"KeywordSearchConfigurationPanel2.timeRadioButton2.toolTipText")); // NOI18N
timeRadioButton3.setText(org.openide.util.NbBundle.getMessage(KeywordSearchConfigurationPanel2.class, "KeywordSearchConfigurationPanel2.timeRadioButton3.text")); // NOI18N timeRadioButton3.setText(org.openide.util.NbBundle.getMessage(KeywordSearchConfigurationPanel2.class,
timeRadioButton3.setToolTipText(org.openide.util.NbBundle.getMessage(KeywordSearchConfigurationPanel2.class, "KeywordSearchConfigurationPanel2.timeRadioButton3.toolTipText")); // NOI18N "KeywordSearchConfigurationPanel2.timeRadioButton3.text")); // NOI18N
timeRadioButton3.setToolTipText(org.openide.util.NbBundle.getMessage(KeywordSearchConfigurationPanel2.class,
"KeywordSearchConfigurationPanel2.timeRadioButton3.toolTipText")); // NOI18N
timeRadioButton4.setText(org.openide.util.NbBundle.getMessage(KeywordSearchConfigurationPanel2.class, "KeywordSearchConfigurationPanel2.timeRadioButton4.text_1")); // NOI18N timeRadioButton4.setText(org.openide.util.NbBundle.getMessage(KeywordSearchConfigurationPanel2.class,
timeRadioButton4.setToolTipText(org.openide.util.NbBundle.getMessage(KeywordSearchConfigurationPanel2.class, "KeywordSearchConfigurationPanel2.timeRadioButton4.toolTipText")); // NOI18N "KeywordSearchConfigurationPanel2.timeRadioButton4.text_1")); // NOI18N
timeRadioButton4.setToolTipText(org.openide.util.NbBundle.getMessage(KeywordSearchConfigurationPanel2.class,
"KeywordSearchConfigurationPanel2.timeRadioButton4.toolTipText")); // NOI18N
javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this); javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
this.setLayout(layout); this.setLayout(layout);
@ -239,14 +257,11 @@ class KeywordSearchConfigurationPanel2 extends javax.swing.JPanel implements Opt
private UpdateFrequency getSelectedTimeValue() { private UpdateFrequency getSelectedTimeValue() {
if (timeRadioButton1.isSelected()) { if (timeRadioButton1.isSelected()) {
return UpdateFrequency.FAST; return UpdateFrequency.FAST;
} } else if (timeRadioButton2.isSelected()) {
else if (timeRadioButton2.isSelected()) {
return UpdateFrequency.AVG; return UpdateFrequency.AVG;
} } else if (timeRadioButton3.isSelected()) {
else if (timeRadioButton3.isSelected()) {
return UpdateFrequency.SLOW; return UpdateFrequency.SLOW;
} } else if (timeRadioButton4.isSelected()) {
else if (timeRadioButton4.isSelected()) {
return UpdateFrequency.SLOWEST; return UpdateFrequency.SLOWEST;
} }
return UpdateFrequency.DEFAULT; return UpdateFrequency.DEFAULT;
@ -282,7 +297,8 @@ class KeywordSearchConfigurationPanel2 extends javax.swing.JPanel implements Opt
int newFilesIndexed = ((Integer) newValue).intValue(); int newFilesIndexed = ((Integer) newValue).intValue();
filesIndexedValue.setText(Integer.toString(newFilesIndexed)); filesIndexedValue.setText(Integer.toString(newFilesIndexed));
try { try {
chunksValLabel.setText(Integer.toString(KeywordSearch.getServer().queryNumIndexedChunks())); chunksValLabel
.setText(Integer.toString(KeywordSearch.getServer().queryNumIndexedChunks()));
} catch (KeywordSearchModuleException ex) { } catch (KeywordSearchModuleException ex) {
logger.log(Level.WARNING, "Could not get number of indexed chunks"); logger.log(Level.WARNING, "Could not get number of indexed chunks");

View File

@ -26,8 +26,11 @@ import java.util.ArrayList;
import java.util.HashMap; import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import org.sleuthkit.autopsy.coreutils.Logger; import org.sleuthkit.autopsy.coreutils.Logger;
import javax.swing.JCheckBox; import javax.swing.JCheckBox;
import org.sleuthkit.autopsy.corecomponents.OptionsPanel; import org.sleuthkit.autopsy.corecomponents.OptionsPanel;
import org.sleuthkit.autopsy.coreutils.StringExtract; import org.sleuthkit.autopsy.coreutils.StringExtract;
import org.sleuthkit.autopsy.coreutils.StringExtract.StringExtractUnicodeTable.SCRIPT; import org.sleuthkit.autopsy.coreutils.StringExtract.StringExtractUnicodeTable.SCRIPT;
@ -40,7 +43,8 @@ class KeywordSearchConfigurationPanel3 extends javax.swing.JPanel implements Opt
private static KeywordSearchConfigurationPanel3 instance = null; private static KeywordSearchConfigurationPanel3 instance = null;
private final Logger logger = Logger.getLogger(KeywordSearchConfigurationPanel3.class.getName()); private final Logger logger = Logger.getLogger(KeywordSearchConfigurationPanel3.class.getName());
private final Map<String, StringExtract.StringExtractUnicodeTable.SCRIPT> scripts = new HashMap<String, StringExtract.StringExtractUnicodeTable.SCRIPT>(); private final Map<String, StringExtract.StringExtractUnicodeTable.SCRIPT> scripts
= new HashMap<String, StringExtract.StringExtractUnicodeTable.SCRIPT>();
private ActionListener updateLanguagesAction; private ActionListener updateLanguagesAction;
private List<SCRIPT> toUpdate; private List<SCRIPT> toUpdate;
@ -97,9 +101,10 @@ class KeywordSearchConfigurationPanel3 extends javax.swing.JPanel implements Opt
sb.append(")"); sb.append(")");
return sb.toString(); return sb.toString();
} }
private void initScriptsCheckBoxes() { private void initScriptsCheckBoxes() {
final List<StringExtract.StringExtractUnicodeTable.SCRIPT> supportedScripts = StringExtract.getSupportedScripts(); final List<StringExtract.StringExtractUnicodeTable.SCRIPT> supportedScripts = StringExtract
.getSupportedScripts();
checkPanel.setLayout(new GridLayout(0, 1)); checkPanel.setLayout(new GridLayout(0, 1));
for (StringExtract.StringExtractUnicodeTable.SCRIPT s : supportedScripts) { for (StringExtract.StringExtractUnicodeTable.SCRIPT s : supportedScripts) {
String text = getLangText(s); String text = getLangText(s);
@ -112,45 +117,49 @@ class KeywordSearchConfigurationPanel3 extends javax.swing.JPanel implements Opt
} }
private void reloadScriptsCheckBoxes() { private void reloadScriptsCheckBoxes() {
boolean utf16 = boolean utf16 =
Boolean.parseBoolean(KeywordSearchSettings.getStringExtractOption(AbstractFileExtract.ExtractOptions.EXTRACT_UTF16.toString())); Boolean.parseBoolean(KeywordSearchSettings.getStringExtractOption(
AbstractFileExtract.ExtractOptions.EXTRACT_UTF16.toString()));
enableUTF16Checkbox.setSelected(utf16); enableUTF16Checkbox.setSelected(utf16);
boolean utf8 = boolean utf8 =
Boolean.parseBoolean(KeywordSearchSettings.getStringExtractOption(AbstractFileExtract.ExtractOptions.EXTRACT_UTF8.toString())); Boolean.parseBoolean(KeywordSearchSettings.getStringExtractOption(
AbstractFileExtract.ExtractOptions.EXTRACT_UTF8.toString()));
enableUTF8Checkbox.setSelected(utf8); enableUTF8Checkbox.setSelected(utf8);
final List<SCRIPT> serviceScripts = KeywordSearchSettings.getStringExtractScripts(); final List<SCRIPT> serviceScripts = KeywordSearchSettings.getStringExtractScripts();
final int components = checkPanel.getComponentCount(); final int components = checkPanel.getComponentCount();
for (int i = 0; i < components; ++i) { for (int i = 0; i < components; ++i) {
JCheckBox ch = (JCheckBox) checkPanel.getComponent(i); JCheckBox ch = (JCheckBox) checkPanel.getComponent(i);
StringExtract.StringExtractUnicodeTable.SCRIPT script = scripts.get(ch.getText()); StringExtract.StringExtractUnicodeTable.SCRIPT script = scripts.get(ch.getText());
ch.setSelected(serviceScripts.contains(script)); ch.setSelected(serviceScripts.contains(script));
} }
} }
private void activateWidgets() { private void activateWidgets() {
reloadScriptsCheckBoxes(); reloadScriptsCheckBoxes();
boolean utf16 = boolean utf16 =
Boolean.parseBoolean(KeywordSearchSettings.getStringExtractOption(AbstractFileExtract.ExtractOptions.EXTRACT_UTF16.toString())); Boolean.parseBoolean(KeywordSearchSettings.getStringExtractOption(
AbstractFileExtract.ExtractOptions.EXTRACT_UTF16.toString()));
enableUTF16Checkbox.setSelected(utf16); enableUTF16Checkbox.setSelected(utf16);
boolean utf8 = boolean utf8 =
Boolean.parseBoolean(KeywordSearchSettings.getStringExtractOption(AbstractFileExtract.ExtractOptions.EXTRACT_UTF8.toString())); Boolean.parseBoolean(KeywordSearchSettings.getStringExtractOption(
AbstractFileExtract.ExtractOptions.EXTRACT_UTF8.toString()));
enableUTF8Checkbox.setSelected(utf8); enableUTF8Checkbox.setSelected(utf8);
final boolean extractEnabled = utf16 || utf8; final boolean extractEnabled = utf16 || utf8;
boolean ingestNotRunning = !IngestManager.getDefault().isIngestRunning() boolean ingestNotRunning = !IngestManager.getDefault().isIngestRunning()
&& ! IngestManager.getDefault().isModuleRunning(KeywordSearchIngestModule.getDefault()); && !IngestManager.getDefault().isModuleRunning(KeywordSearchIngestModule.getDefault());
//enable / disable checboxes //enable / disable checboxes
activateScriptsCheckboxes(extractEnabled && ingestNotRunning); activateScriptsCheckboxes(extractEnabled && ingestNotRunning);
enableUTF16Checkbox.setEnabled(ingestNotRunning); enableUTF16Checkbox.setEnabled(ingestNotRunning);
@ -173,7 +182,9 @@ class KeywordSearchConfigurationPanel3 extends javax.swing.JPanel implements Opt
enableUTF16Checkbox = new javax.swing.JCheckBox(); enableUTF16Checkbox = new javax.swing.JCheckBox();
ingestSettingsLabel = new javax.swing.JLabel(); ingestSettingsLabel = new javax.swing.JLabel();
org.openide.awt.Mnemonics.setLocalizedText(languagesLabel, org.openide.util.NbBundle.getMessage(KeywordSearchConfigurationPanel3.class, "KeywordSearchConfigurationPanel3.languagesLabel.text")); // NOI18N org.openide.awt.Mnemonics.setLocalizedText(languagesLabel, org.openide.util.NbBundle.getMessage(
KeywordSearchConfigurationPanel3.class,
"KeywordSearchConfigurationPanel3.languagesLabel.text")); // NOI18N
langPanel.setPreferredSize(new java.awt.Dimension(430, 361)); langPanel.setPreferredSize(new java.awt.Dimension(430, 361));
@ -182,31 +193,37 @@ class KeywordSearchConfigurationPanel3 extends javax.swing.JPanel implements Opt
javax.swing.GroupLayout checkPanelLayout = new javax.swing.GroupLayout(checkPanel); javax.swing.GroupLayout checkPanelLayout = new javax.swing.GroupLayout(checkPanel);
checkPanel.setLayout(checkPanelLayout); checkPanel.setLayout(checkPanelLayout);
checkPanelLayout.setHorizontalGroup( checkPanelLayout.setHorizontalGroup(
checkPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) checkPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGap(0, 428, Short.MAX_VALUE) .addGap(0, 428, Short.MAX_VALUE)
); );
checkPanelLayout.setVerticalGroup( checkPanelLayout.setVerticalGroup(
checkPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) checkPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGap(0, 395, Short.MAX_VALUE) .addGap(0, 395, Short.MAX_VALUE)
); );
langPanel.setViewportView(checkPanel); langPanel.setViewportView(checkPanel);
org.openide.awt.Mnemonics.setLocalizedText(enableUTF8Checkbox, org.openide.util.NbBundle.getMessage(KeywordSearchConfigurationPanel3.class, "KeywordSearchConfigurationPanel3.enableUTF8Checkbox.text")); // NOI18N org.openide.awt.Mnemonics.setLocalizedText(enableUTF8Checkbox, org.openide.util.NbBundle.getMessage(
KeywordSearchConfigurationPanel3.class,
"KeywordSearchConfigurationPanel3.enableUTF8Checkbox.text")); // NOI18N
enableUTF8Checkbox.addActionListener(new java.awt.event.ActionListener() { enableUTF8Checkbox.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) { public void actionPerformed(java.awt.event.ActionEvent evt) {
enableUTF8CheckboxActionPerformed(evt); enableUTF8CheckboxActionPerformed(evt);
} }
}); });
org.openide.awt.Mnemonics.setLocalizedText(enableUTF16Checkbox, org.openide.util.NbBundle.getMessage(KeywordSearchConfigurationPanel3.class, "KeywordSearchConfigurationPanel3.enableUTF16Checkbox.text")); // NOI18N org.openide.awt.Mnemonics.setLocalizedText(enableUTF16Checkbox, org.openide.util.NbBundle.getMessage(
KeywordSearchConfigurationPanel3.class,
"KeywordSearchConfigurationPanel3.enableUTF16Checkbox.text")); // NOI18N
enableUTF16Checkbox.addActionListener(new java.awt.event.ActionListener() { enableUTF16Checkbox.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) { public void actionPerformed(java.awt.event.ActionEvent evt) {
enableUTF16CheckboxActionPerformed(evt); enableUTF16CheckboxActionPerformed(evt);
} }
}); });
org.openide.awt.Mnemonics.setLocalizedText(ingestSettingsLabel, org.openide.util.NbBundle.getMessage(KeywordSearchConfigurationPanel3.class, "KeywordSearchConfigurationPanel3.ingestSettingsLabel.text")); // NOI18N org.openide.awt.Mnemonics.setLocalizedText(ingestSettingsLabel, org.openide.util.NbBundle.getMessage(
KeywordSearchConfigurationPanel3.class,
"KeywordSearchConfigurationPanel3.ingestSettingsLabel.text")); // NOI18N
javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this); javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
this.setLayout(layout); this.setLayout(layout);
@ -243,18 +260,20 @@ class KeywordSearchConfigurationPanel3 extends javax.swing.JPanel implements Opt
); );
}// </editor-fold>//GEN-END:initComponents }// </editor-fold>//GEN-END:initComponents
private void enableUTF8CheckboxActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_enableUTF8CheckboxActionPerformed private void enableUTF8CheckboxActionPerformed(
java.awt.event.ActionEvent evt) {//GEN-FIRST:event_enableUTF8CheckboxActionPerformed
boolean selected = this.enableUTF8Checkbox.isSelected(); boolean selected = this.enableUTF8Checkbox.isSelected();
activateScriptsCheckboxes(selected || this.enableUTF16Checkbox.isSelected()); activateScriptsCheckboxes(selected || this.enableUTF16Checkbox.isSelected());
}//GEN-LAST:event_enableUTF8CheckboxActionPerformed }//GEN-LAST:event_enableUTF8CheckboxActionPerformed
private void enableUTF16CheckboxActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_enableUTF16CheckboxActionPerformed private void enableUTF16CheckboxActionPerformed(
java.awt.event.ActionEvent evt) {//GEN-FIRST:event_enableUTF16CheckboxActionPerformed
boolean selected = this.enableUTF16Checkbox.isSelected(); boolean selected = this.enableUTF16Checkbox.isSelected();
activateScriptsCheckboxes(selected || this.enableUTF8Checkbox.isSelected()); activateScriptsCheckboxes(selected || this.enableUTF8Checkbox.isSelected());
}//GEN-LAST:event_enableUTF16CheckboxActionPerformed }//GEN-LAST:event_enableUTF16CheckboxActionPerformed
@ -270,19 +289,19 @@ class KeywordSearchConfigurationPanel3 extends javax.swing.JPanel implements Opt
@Override @Override
public void store() { public void store() {
KeywordSearchSettings.setStringExtractOption(AbstractFileExtract.ExtractOptions.EXTRACT_UTF8.toString(), KeywordSearchSettings.setStringExtractOption(AbstractFileExtract.ExtractOptions.EXTRACT_UTF8.toString(),
Boolean.toString(enableUTF8Checkbox.isSelected())); Boolean.toString(enableUTF8Checkbox.isSelected()));
KeywordSearchSettings.setStringExtractOption(AbstractFileExtract.ExtractOptions.EXTRACT_UTF16.toString(), KeywordSearchSettings.setStringExtractOption(AbstractFileExtract.ExtractOptions.EXTRACT_UTF16.toString(),
Boolean.toString(enableUTF16Checkbox.isSelected())); Boolean.toString(enableUTF16Checkbox.isSelected()));
if(toUpdate!=null) { if (toUpdate != null) {
KeywordSearchSettings.setStringExtractScripts(toUpdate); KeywordSearchSettings.setStringExtractScripts(toUpdate);
} }
} }
@Override @Override
public void load() { public void load() {
activateWidgets(); activateWidgets();
} }
} }

View File

@ -33,6 +33,7 @@ import java.util.logging.Level;
import org.openide.util.NbBundle; import org.openide.util.NbBundle;
import org.sleuthkit.autopsy.coreutils.Logger; import org.sleuthkit.autopsy.coreutils.Logger;
import java.util.regex.Pattern; import java.util.regex.Pattern;
import java.util.regex.PatternSyntaxException; import java.util.regex.PatternSyntaxException;
import javax.swing.DefaultListSelectionModel; import javax.swing.DefaultListSelectionModel;
@ -47,13 +48,14 @@ import javax.swing.filechooser.FileNameExtensionFilter;
import javax.swing.table.AbstractTableModel; import javax.swing.table.AbstractTableModel;
import javax.swing.table.TableCellRenderer; import javax.swing.table.TableCellRenderer;
import javax.swing.table.TableColumn; import javax.swing.table.TableColumn;
import org.sleuthkit.autopsy.corecomponents.OptionsPanel; import org.sleuthkit.autopsy.corecomponents.OptionsPanel;
import org.sleuthkit.autopsy.ingest.IngestManager; import org.sleuthkit.autopsy.ingest.IngestManager;
import org.sleuthkit.autopsy.ingest.IngestManager.IngestModuleEvent; import org.sleuthkit.autopsy.ingest.IngestManager.IngestModuleEvent;
import org.sleuthkit.datamodel.BlackboardAttribute; import org.sleuthkit.datamodel.BlackboardAttribute;
/** /**
* KeywordSearchEditListPanel widget to manage keywords in lists * KeywordSearchEditListPanel widget to manage keywords in lists
*/ */
class KeywordSearchEditListPanel extends javax.swing.JPanel implements ListSelectionListener, OptionsPanel { class KeywordSearchEditListPanel extends javax.swing.JPanel implements ListSelectionListener, OptionsPanel {
@ -61,24 +63,32 @@ class KeywordSearchEditListPanel extends javax.swing.JPanel implements ListSelec
private KeywordTableModel tableModel; private KeywordTableModel tableModel;
private KeywordSearchListsAbstract.KeywordSearchList currentKeywordList; private KeywordSearchListsAbstract.KeywordSearchList currentKeywordList;
private boolean ingestRunning; private boolean ingestRunning;
/** Creates new form KeywordSearchEditListPanel */ /**
* Creates new form KeywordSearchEditListPanel
*/
KeywordSearchEditListPanel() { KeywordSearchEditListPanel() {
tableModel = new KeywordTableModel(); tableModel = new KeywordTableModel();
initComponents(); initComponents();
customizeComponents(); customizeComponents();
} }
private void customizeComponents() { private void customizeComponents() {
chRegex.setToolTipText(NbBundle.getMessage(this.getClass(), "KeywordSearchEditListPanel.customizeComponents.kwReToolTip")); chRegex.setToolTipText(
addWordButton.setToolTipText((NbBundle.getMessage(this.getClass(), "KeywordSearchEditListPanel.customizeComponents.addWordToolTip"))); NbBundle.getMessage(this.getClass(), "KeywordSearchEditListPanel.customizeComponents.kwReToolTip"));
addWordField.setToolTipText(NbBundle.getMessage(this.getClass(), "KeywordSearchEditListPanel.customizeComponents.enterNewWordToolTip")); addWordButton.setToolTipText((NbBundle
exportButton.setToolTipText(NbBundle.getMessage(this.getClass(), "KeywordSearchEditListPanel.customizeComponents.exportToFile")); .getMessage(this.getClass(), "KeywordSearchEditListPanel.customizeComponents.addWordToolTip")));
saveListButton.setToolTipText(NbBundle.getMessage(this.getClass(), "KeywordSearchEditListPanel.customizeComponents.saveCurrentWIthNewNameToolTip")); addWordField.setToolTipText(NbBundle.getMessage(this.getClass(),
deleteWordButton.setToolTipText(NbBundle.getMessage(this.getClass(), "KeywordSearchEditListPanel.customizeComponents.removeSelectedMsg")); "KeywordSearchEditListPanel.customizeComponents.enterNewWordToolTip"));
exportButton.setToolTipText(
NbBundle.getMessage(this.getClass(), "KeywordSearchEditListPanel.customizeComponents.exportToFile"));
saveListButton.setToolTipText(NbBundle.getMessage(this.getClass(),
"KeywordSearchEditListPanel.customizeComponents.saveCurrentWIthNewNameToolTip"));
deleteWordButton.setToolTipText(NbBundle.getMessage(this.getClass(),
"KeywordSearchEditListPanel.customizeComponents.removeSelectedMsg"));
//keywordTable.setAutoscrolls(true); //keywordTable.setAutoscrolls(true);
//keywordTable.setTableHeader(null); //keywordTable.setTableHeader(null);
@ -105,7 +115,7 @@ class KeywordSearchEditListPanel extends javax.swing.JPanel implements ListSelec
final ListSelectionModel lsm = keywordTable.getSelectionModel(); final ListSelectionModel lsm = keywordTable.getSelectionModel();
lsm.addListSelectionListener(new ListSelectionListener() { lsm.addListSelectionListener(new ListSelectionListener() {
@Override @Override
public void valueChanged(ListSelectionEvent e) { public void valueChanged(ListSelectionEvent e) {
if (lsm.isSelectionEmpty() || currentKeywordList.isLocked()) { if (lsm.isSelectionEmpty() || currentKeywordList.isLocked()) {
@ -114,7 +124,7 @@ class KeywordSearchEditListPanel extends javax.swing.JPanel implements ListSelec
} else { } else {
deleteWordButton.setEnabled(true); deleteWordButton.setEnabled(true);
} }
//show selector if available //show selector if available
DefaultListSelectionModel selModel = (DefaultListSelectionModel) e.getSource(); DefaultListSelectionModel selModel = (DefaultListSelectionModel) e.getSource();
if (!selModel.getValueIsAdjusting()) { if (!selModel.getValueIsAdjusting()) {
@ -133,7 +143,7 @@ class KeywordSearchEditListPanel extends javax.swing.JPanel implements ListSelec
}); });
//loadDefaultKeywords(); //loadDefaultKeywords();
initButtons(); initButtons();
@ -160,7 +170,6 @@ class KeywordSearchEditListPanel extends javax.swing.JPanel implements ListSelec
selectAllMenuItem.addActionListener(actList); selectAllMenuItem.addActionListener(actList);
if (IngestManager.getDefault().isModuleRunning(KeywordSearchIngestModule.getDefault())) { if (IngestManager.getDefault().isModuleRunning(KeywordSearchIngestModule.getDefault())) {
initIngest(0); initIngest(0);
} else { } else {
@ -173,13 +182,13 @@ class KeywordSearchEditListPanel extends javax.swing.JPanel implements ListSelec
public void propertyChange(PropertyChangeEvent evt) { public void propertyChange(PropertyChangeEvent evt) {
String changed = evt.getPropertyName(); String changed = evt.getPropertyName();
Object oldValue = evt.getOldValue(); Object oldValue = evt.getOldValue();
if (changed.equals(IngestModuleEvent.COMPLETED.toString() ) if (changed.equals(IngestModuleEvent.COMPLETED.toString())
&& ((String) oldValue).equals(KeywordSearchIngestModule.MODULE_NAME)) { && ((String) oldValue).equals(KeywordSearchIngestModule.MODULE_NAME)) {
initIngest(1); initIngest(1);
} else if (changed.equals(IngestModuleEvent.STARTED.toString() ) } else if (changed.equals(IngestModuleEvent.STARTED.toString())
&& ((String) oldValue).equals(KeywordSearchIngestModule.MODULE_NAME)) { && ((String) oldValue).equals(KeywordSearchIngestModule.MODULE_NAME)) {
initIngest(0); initIngest(0);
} else if (changed.equals(IngestModuleEvent.STOPPED.toString() ) } else if (changed.equals(IngestModuleEvent.STOPPED.toString())
&& ((String) oldValue).equals(KeywordSearchIngestModule.MODULE_NAME)) { && ((String) oldValue).equals(KeywordSearchIngestModule.MODULE_NAME)) {
initIngest(1); initIngest(1);
} }
@ -187,11 +196,11 @@ class KeywordSearchEditListPanel extends javax.swing.JPanel implements ListSelec
}); });
} }
/** /**
* Initialize this panel depending on whether ingest is running * Initialize this panel depending on whether ingest is running
* @param running *
* case 0: ingest running * @param running case 0: ingest running
* case 1: ingest not running * case 1: ingest not running
*/ */
private void initIngest(int running) { private void initIngest(int running) {
switch (running) { switch (running) {
@ -253,7 +262,8 @@ class KeywordSearchEditListPanel extends javax.swing.JPanel implements ListSelec
} }
} }
/** This method is called from within the constructor to /**
* This method is called from within the constructor to
* initialize the form. * initialize the form.
* WARNING: Do NOT modify this code. The content of this method is * WARNING: Do NOT modify this code. The content of this method is
* always regenerated by the Form Editor. * always regenerated by the Form Editor.
@ -286,16 +296,20 @@ class KeywordSearchEditListPanel extends javax.swing.JPanel implements ListSelec
saveListButton = new javax.swing.JButton(); saveListButton = new javax.swing.JButton();
exportButton = new javax.swing.JButton(); exportButton = new javax.swing.JButton();
cutMenuItem.setText(org.openide.util.NbBundle.getMessage(KeywordSearchEditListPanel.class, "KeywordSearchEditListPanel.cutMenuItem.text")); // NOI18N cutMenuItem.setText(org.openide.util.NbBundle.getMessage(KeywordSearchEditListPanel.class,
"KeywordSearchEditListPanel.cutMenuItem.text")); // NOI18N
rightClickMenu.add(cutMenuItem); rightClickMenu.add(cutMenuItem);
copyMenuItem.setText(org.openide.util.NbBundle.getMessage(KeywordSearchEditListPanel.class, "KeywordSearchEditListPanel.copyMenuItem.text")); // NOI18N copyMenuItem.setText(org.openide.util.NbBundle.getMessage(KeywordSearchEditListPanel.class,
"KeywordSearchEditListPanel.copyMenuItem.text")); // NOI18N
rightClickMenu.add(copyMenuItem); rightClickMenu.add(copyMenuItem);
pasteMenuItem.setText(org.openide.util.NbBundle.getMessage(KeywordSearchEditListPanel.class, "KeywordSearchEditListPanel.pasteMenuItem.text")); // NOI18N pasteMenuItem.setText(org.openide.util.NbBundle.getMessage(KeywordSearchEditListPanel.class,
"KeywordSearchEditListPanel.pasteMenuItem.text")); // NOI18N
rightClickMenu.add(pasteMenuItem); rightClickMenu.add(pasteMenuItem);
selectAllMenuItem.setText(org.openide.util.NbBundle.getMessage(KeywordSearchEditListPanel.class, "KeywordSearchEditListPanel.selectAllMenuItem.text")); // NOI18N selectAllMenuItem.setText(org.openide.util.NbBundle.getMessage(KeywordSearchEditListPanel.class,
"KeywordSearchEditListPanel.selectAllMenuItem.text")); // NOI18N
rightClickMenu.add(selectAllMenuItem); rightClickMenu.add(selectAllMenuItem);
setMinimumSize(new java.awt.Dimension(340, 300)); setMinimumSize(new java.awt.Dimension(340, 300));
@ -310,35 +324,40 @@ class KeywordSearchEditListPanel extends javax.swing.JPanel implements ListSelec
keywordTable.getTableHeader().setReorderingAllowed(false); keywordTable.getTableHeader().setReorderingAllowed(false);
jScrollPane1.setViewportView(keywordTable); jScrollPane1.setViewportView(keywordTable);
useForIngestCheckbox.setText(org.openide.util.NbBundle.getMessage(KeywordSearchEditListPanel.class, "KeywordSearchEditListPanel.useForIngestCheckbox.text")); // NOI18N useForIngestCheckbox.setText(org.openide.util.NbBundle.getMessage(KeywordSearchEditListPanel.class,
"KeywordSearchEditListPanel.useForIngestCheckbox.text")); // NOI18N
useForIngestCheckbox.addActionListener(new java.awt.event.ActionListener() { useForIngestCheckbox.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) { public void actionPerformed(java.awt.event.ActionEvent evt) {
useForIngestCheckboxActionPerformed(evt); useForIngestCheckboxActionPerformed(evt);
} }
}); });
addWordButton.setText(org.openide.util.NbBundle.getMessage(KeywordSearchEditListPanel.class, "KeywordSearchEditListPanel.addWordButton.text")); // NOI18N addWordButton.setText(org.openide.util.NbBundle.getMessage(KeywordSearchEditListPanel.class,
"KeywordSearchEditListPanel.addWordButton.text")); // NOI18N
addWordButton.addActionListener(new java.awt.event.ActionListener() { addWordButton.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) { public void actionPerformed(java.awt.event.ActionEvent evt) {
addWordButtonActionPerformed(evt); addWordButtonActionPerformed(evt);
} }
}); });
addWordField.setText(org.openide.util.NbBundle.getMessage(KeywordSearchEditListPanel.class, "KeywordSearchEditListPanel.addWordField.text")); // NOI18N addWordField.setText(org.openide.util.NbBundle.getMessage(KeywordSearchEditListPanel.class,
"KeywordSearchEditListPanel.addWordField.text")); // NOI18N
addWordField.addActionListener(new java.awt.event.ActionListener() { addWordField.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) { public void actionPerformed(java.awt.event.ActionEvent evt) {
addWordFieldActionPerformed(evt); addWordFieldActionPerformed(evt);
} }
}); });
chRegex.setText(org.openide.util.NbBundle.getMessage(KeywordSearchEditListPanel.class, "KeywordSearchEditListPanel.chRegex.text")); // NOI18N chRegex.setText(org.openide.util.NbBundle.getMessage(KeywordSearchEditListPanel.class,
"KeywordSearchEditListPanel.chRegex.text")); // NOI18N
chRegex.addActionListener(new java.awt.event.ActionListener() { chRegex.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) { public void actionPerformed(java.awt.event.ActionEvent evt) {
chRegexActionPerformed(evt); chRegexActionPerformed(evt);
} }
}); });
deleteWordButton.setText(org.openide.util.NbBundle.getMessage(KeywordSearchEditListPanel.class, "KeywordSearchEditListPanel.deleteWordButton.text")); // NOI18N deleteWordButton.setText(org.openide.util.NbBundle.getMessage(KeywordSearchEditListPanel.class,
"KeywordSearchEditListPanel.deleteWordButton.text")); // NOI18N
deleteWordButton.addActionListener(new java.awt.event.ActionListener() { deleteWordButton.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) { public void actionPerformed(java.awt.event.ActionEvent evt) {
deleteWordButtonActionPerformed(evt); deleteWordButtonActionPerformed(evt);
@ -374,28 +393,39 @@ class KeywordSearchEditListPanel extends javax.swing.JPanel implements ListSelec
.addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
); );
ingestMessagesCheckbox.setText(org.openide.util.NbBundle.getMessage(KeywordSearchEditListPanel.class, "KeywordSearchEditListPanel.ingestMessagesCheckbox.text")); // NOI18N ingestMessagesCheckbox.setText(org.openide.util.NbBundle.getMessage(KeywordSearchEditListPanel.class,
ingestMessagesCheckbox.setToolTipText(org.openide.util.NbBundle.getMessage(KeywordSearchEditListPanel.class, "KeywordSearchEditListPanel.ingestMessagesCheckbox.toolTipText")); // NOI18N "KeywordSearchEditListPanel.ingestMessagesCheckbox.text")); // NOI18N
ingestMessagesCheckbox.setToolTipText(org.openide.util.NbBundle.getMessage(KeywordSearchEditListPanel.class,
"KeywordSearchEditListPanel.ingestMessagesCheckbox.toolTipText")); // NOI18N
ingestMessagesCheckbox.addActionListener(new java.awt.event.ActionListener() { ingestMessagesCheckbox.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) { public void actionPerformed(java.awt.event.ActionEvent evt) {
ingestMessagesCheckboxActionPerformed(evt); ingestMessagesCheckboxActionPerformed(evt);
} }
}); });
keywordsLabel.setText(org.openide.util.NbBundle.getMessage(KeywordSearchEditListPanel.class, "KeywordSearchEditListPanel.keywordsLabel.text")); // NOI18N keywordsLabel.setText(org.openide.util.NbBundle.getMessage(KeywordSearchEditListPanel.class,
"KeywordSearchEditListPanel.keywordsLabel.text")); // NOI18N
keywordOptionsLabel.setText(org.openide.util.NbBundle.getMessage(KeywordSearchEditListPanel.class, "KeywordSearchEditListPanel.keywordOptionsLabel.text")); // NOI18N keywordOptionsLabel.setText(org.openide.util.NbBundle.getMessage(KeywordSearchEditListPanel.class,
"KeywordSearchEditListPanel.keywordOptionsLabel.text")); // NOI18N
listOptionsLabel.setText(org.openide.util.NbBundle.getMessage(KeywordSearchEditListPanel.class, "KeywordSearchEditListPanel.listOptionsLabel.text")); // NOI18N listOptionsLabel.setText(org.openide.util.NbBundle.getMessage(KeywordSearchEditListPanel.class,
"KeywordSearchEditListPanel.listOptionsLabel.text")); // NOI18N
deleteListButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/org/sleuthkit/autopsy/keywordsearch/delete16.png"))); // NOI18N deleteListButton.setIcon(new javax.swing.ImageIcon(
deleteListButton.setText(org.openide.util.NbBundle.getMessage(KeywordSearchEditListPanel.class, "KeywordSearchEditListPanel.deleteListButton.text")); // NOI18N getClass().getResource("/org/sleuthkit/autopsy/keywordsearch/delete16.png"))); // NOI18N
deleteListButton.setText(org.openide.util.NbBundle.getMessage(KeywordSearchEditListPanel.class,
"KeywordSearchEditListPanel.deleteListButton.text")); // NOI18N
saveListButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/org/sleuthkit/autopsy/keywordsearch/save16.png"))); // NOI18N saveListButton.setIcon(new javax.swing.ImageIcon(
saveListButton.setText(org.openide.util.NbBundle.getMessage(KeywordSearchEditListPanel.class, "KeywordSearchEditListPanel.saveListButton.text")); // NOI18N getClass().getResource("/org/sleuthkit/autopsy/keywordsearch/save16.png"))); // NOI18N
saveListButton.setText(org.openide.util.NbBundle.getMessage(KeywordSearchEditListPanel.class,
"KeywordSearchEditListPanel.saveListButton.text")); // NOI18N
exportButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/org/sleuthkit/autopsy/keywordsearch/export16.png"))); // NOI18N exportButton.setIcon(new javax.swing.ImageIcon(
exportButton.setText(org.openide.util.NbBundle.getMessage(KeywordSearchEditListPanel.class, "KeywordSearchEditListPanel.exportButton.text")); // NOI18N getClass().getResource("/org/sleuthkit/autopsy/keywordsearch/export16.png"))); // NOI18N
exportButton.setText(org.openide.util.NbBundle.getMessage(KeywordSearchEditListPanel.class,
"KeywordSearchEditListPanel.exportButton.text")); // NOI18N
exportButton.addActionListener(new java.awt.event.ActionListener() { exportButton.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) { public void actionPerformed(java.awt.event.ActionEvent evt) {
exportButtonActionPerformed(evt); exportButtonActionPerformed(evt);
@ -474,16 +504,19 @@ class KeywordSearchEditListPanel extends javax.swing.JPanel implements ListSelec
javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this); javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
this.setLayout(layout); this.setLayout(layout);
layout.setHorizontalGroup( layout.setHorizontalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(listEditorPanel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) .addComponent(listEditorPanel, javax.swing.GroupLayout.DEFAULT_SIZE,
javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
); );
layout.setVerticalGroup( layout.setVerticalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(listEditorPanel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) .addComponent(listEditorPanel, javax.swing.GroupLayout.DEFAULT_SIZE,
javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
); );
}// </editor-fold>//GEN-END:initComponents }// </editor-fold>//GEN-END:initComponents
private void addWordButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_addWordButtonActionPerformed private void addWordButtonActionPerformed(
java.awt.event.ActionEvent evt) {//GEN-FIRST:event_addWordButtonActionPerformed
String newWord = addWordField.getText().trim(); String newWord = addWordField.getText().trim();
boolean isLiteral = !chRegex.isSelected(); boolean isLiteral = !chRegex.isSelected();
final Keyword keyword = new Keyword(newWord, isLiteral); final Keyword keyword = new Keyword(newWord, isLiteral);
@ -491,8 +524,11 @@ class KeywordSearchEditListPanel extends javax.swing.JPanel implements ListSelec
if (newWord.equals("")) { if (newWord.equals("")) {
return; return;
} else if (currentKeywordList.hasKeyword(keyword)) { } else if (currentKeywordList.hasKeyword(keyword)) {
KeywordSearchUtil.displayDialog(NbBundle.getMessage(this.getClass(), "KeywordSearchEditListPanel.newKwTitle"), KeywordSearchUtil
NbBundle.getMessage(this.getClass(), "KeywordSearchEditListPanel.addWordButtonAction.kwAlreadyExistsMsg"), KeywordSearchUtil.DIALOG_MESSAGE_TYPE.INFO); .displayDialog(NbBundle.getMessage(this.getClass(), "KeywordSearchEditListPanel.newKwTitle"),
NbBundle.getMessage(this.getClass(),
"KeywordSearchEditListPanel.addWordButtonAction.kwAlreadyExistsMsg"),
KeywordSearchUtil.DIALOG_MESSAGE_TYPE.INFO);
return; return;
} }
@ -507,8 +543,10 @@ class KeywordSearchEditListPanel extends javax.swing.JPanel implements ListSelec
valid = false; valid = false;
} }
if (!valid) { if (!valid) {
KeywordSearchUtil.displayDialog(NbBundle.getMessage(this.getClass(), "KeywordSearchEditListPanel.newKwTitle"), KeywordSearchUtil
NbBundle.getMessage(this.getClass(), "KeywordSearchEditListPanel.invalidKwMsg"), KeywordSearchUtil.DIALOG_MESSAGE_TYPE.ERROR); .displayDialog(NbBundle.getMessage(this.getClass(), "KeywordSearchEditListPanel.newKwTitle"),
NbBundle.getMessage(this.getClass(), "KeywordSearchEditListPanel.invalidKwMsg"),
KeywordSearchUtil.DIALOG_MESSAGE_TYPE.ERROR);
return; return;
} }
@ -521,29 +559,36 @@ class KeywordSearchEditListPanel extends javax.swing.JPanel implements ListSelec
initButtons(); initButtons();
}//GEN-LAST:event_addWordButtonActionPerformed }//GEN-LAST:event_addWordButtonActionPerformed
private void deleteWordButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_deleteWordButtonActionPerformed private void deleteWordButtonActionPerformed(
if (KeywordSearchUtil.displayConfirmDialog(NbBundle.getMessage(this.getClass(), "KeywordSearchEditListPanel.removeKwMsg") java.awt.event.ActionEvent evt) {//GEN-FIRST:event_deleteWordButtonActionPerformed
, NbBundle.getMessage(this.getClass(), "KeywordSearchEditListPanel.deleteWordButtonActionPerformed.delConfirmMsg") if (KeywordSearchUtil
, KeywordSearchUtil.DIALOG_MESSAGE_TYPE.WARN) ) { .displayConfirmDialog(NbBundle.getMessage(this.getClass(), "KeywordSearchEditListPanel.removeKwMsg")
, NbBundle.getMessage(this.getClass(),
tableModel.deleteSelected(keywordTable.getSelectedRows()); "KeywordSearchEditListPanel.deleteWordButtonActionPerformed.delConfirmMsg")
KeywordSearchListsXML.getCurrent().addList(currentKeywordList); , KeywordSearchUtil.DIALOG_MESSAGE_TYPE.WARN)) {
initButtons();
tableModel.deleteSelected(keywordTable.getSelectedRows());
KeywordSearchListsXML.getCurrent().addList(currentKeywordList);
initButtons();
} }
}//GEN-LAST:event_deleteWordButtonActionPerformed }//GEN-LAST:event_deleteWordButtonActionPerformed
private void addWordFieldActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_addWordFieldActionPerformed private void addWordFieldActionPerformed(
java.awt.event.ActionEvent evt) {//GEN-FIRST:event_addWordFieldActionPerformed
addWordButtonActionPerformed(evt); addWordButtonActionPerformed(evt);
}//GEN-LAST:event_addWordFieldActionPerformed }//GEN-LAST:event_addWordFieldActionPerformed
private void exportButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_exportButtonActionPerformed private void exportButtonActionPerformed(
java.awt.event.ActionEvent evt) {//GEN-FIRST:event_exportButtonActionPerformed
final String FEATURE_NAME = "Keyword List Export"; final String FEATURE_NAME = "Keyword List Export";
JFileChooser chooser = new JFileChooser(); JFileChooser chooser = new JFileChooser();
final String EXTENSION = "xml"; final String EXTENSION = "xml";
FileNameExtensionFilter filter = new FileNameExtensionFilter( FileNameExtensionFilter filter = new FileNameExtensionFilter(
NbBundle.getMessage(this.getClass(), "KeywordSearchEditListPanel.exportButtonActionPerformed.fileFilterLabel"), EXTENSION); NbBundle.getMessage(this.getClass(),
"KeywordSearchEditListPanel.exportButtonActionPerformed.fileFilterLabel"),
EXTENSION);
chooser.setFileFilter(filter); chooser.setFileFilter(filter);
chooser.setSelectedFile(new File(currentKeywordList.getName())); chooser.setSelectedFile(new File(currentKeywordList.getName()));
chooser.setFileSelectionMode(JFileChooser.FILES_ONLY); chooser.setFileSelectionMode(JFileChooser.FILES_ONLY);
@ -565,8 +610,10 @@ class KeywordSearchEditListPanel extends javax.swing.JPanel implements ListSelec
boolean shouldWrite = true; boolean shouldWrite = true;
if (selFile.exists()) { if (selFile.exists()) {
shouldWrite = KeywordSearchUtil.displayConfirmDialog(FEATURE_NAME, shouldWrite = KeywordSearchUtil.displayConfirmDialog(FEATURE_NAME,
NbBundle.getMessage(this.getClass(), "KeywordSearchEditListPanel.exportButtonActionPerformed.fileExistPrompt", NbBundle.getMessage(this.getClass(),
selFile.getName()), KeywordSearchUtil.DIALOG_MESSAGE_TYPE.WARN); "KeywordSearchEditListPanel.exportButtonActionPerformed.fileExistPrompt",
selFile.getName()),
KeywordSearchUtil.DIALOG_MESSAGE_TYPE.WARN);
} }
if (!shouldWrite) { if (!shouldWrite) {
return; return;
@ -575,14 +622,16 @@ class KeywordSearchEditListPanel extends javax.swing.JPanel implements ListSelec
KeywordSearchListsXML reader = KeywordSearchListsXML.getCurrent(); KeywordSearchListsXML reader = KeywordSearchListsXML.getCurrent();
List<KeywordSearchListsAbstract.KeywordSearchList> toWrite = new ArrayList<KeywordSearchListsAbstract.KeywordSearchList>(); List<KeywordSearchListsAbstract.KeywordSearchList> toWrite
= new ArrayList<KeywordSearchListsAbstract.KeywordSearchList>();
toWrite.add(reader.getList(currentKeywordList.getName())); toWrite.add(reader.getList(currentKeywordList.getName()));
final KeywordSearchListsXML exporter = new KeywordSearchListsXML(fileAbs); final KeywordSearchListsXML exporter = new KeywordSearchListsXML(fileAbs);
boolean written = exporter.saveLists(toWrite); boolean written = exporter.saveLists(toWrite);
if (written) { if (written) {
KeywordSearchUtil.displayDialog(FEATURE_NAME, KeywordSearchUtil.displayDialog(FEATURE_NAME,
NbBundle.getMessage(this.getClass(), "KeywordSearchEditListPanel.exportButtonActionPerformed.kwListExportedMsg"), NbBundle.getMessage(this.getClass(),
KeywordSearchUtil.DIALOG_MESSAGE_TYPE.INFO); "KeywordSearchEditListPanel.exportButtonActionPerformed.kwListExportedMsg"),
KeywordSearchUtil.DIALOG_MESSAGE_TYPE.INFO);
} }
} }
}//GEN-LAST:event_exportButtonActionPerformed }//GEN-LAST:event_exportButtonActionPerformed
@ -590,14 +639,16 @@ class KeywordSearchEditListPanel extends javax.swing.JPanel implements ListSelec
private void chRegexActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_chRegexActionPerformed private void chRegexActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_chRegexActionPerformed
}//GEN-LAST:event_chRegexActionPerformed }//GEN-LAST:event_chRegexActionPerformed
private void useForIngestCheckboxActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_useForIngestCheckboxActionPerformed private void useForIngestCheckboxActionPerformed(
ingestMessagesCheckbox.setEnabled(useForIngestCheckbox.isSelected()); java.awt.event.ActionEvent evt) {//GEN-FIRST:event_useForIngestCheckboxActionPerformed
currentKeywordList.setUseForIngest(useForIngestCheckbox.isSelected()); ingestMessagesCheckbox.setEnabled(useForIngestCheckbox.isSelected());
KeywordSearchListsXML updater = KeywordSearchListsXML.getCurrent(); currentKeywordList.setUseForIngest(useForIngestCheckbox.isSelected());
updater.addList(currentKeywordList); KeywordSearchListsXML updater = KeywordSearchListsXML.getCurrent();
}//GEN-LAST:event_useForIngestCheckboxActionPerformed updater.addList(currentKeywordList);
}//GEN-LAST:event_useForIngestCheckboxActionPerformed
private void ingestMessagesCheckboxActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_ingestMessagesCheckboxActionPerformed private void ingestMessagesCheckboxActionPerformed(
java.awt.event.ActionEvent evt) {//GEN-FIRST:event_ingestMessagesCheckboxActionPerformed
currentKeywordList.setIngestMessages(ingestMessagesCheckbox.isSelected()); currentKeywordList.setIngestMessages(ingestMessagesCheckbox.isSelected());
KeywordSearchListsXML updater = KeywordSearchListsXML.getCurrent(); KeywordSearchListsXML updater = KeywordSearchListsXML.getCurrent();
updater.addList(currentKeywordList); updater.addList(currentKeywordList);
@ -658,19 +709,19 @@ private void useForIngestCheckboxActionPerformed(java.awt.event.ActionEvent evt)
public void load() { public void load() {
// Implemented by parent panel // Implemented by parent panel
} }
KeywordSearchListsAbstract.KeywordSearchList getCurrentKeywordList() { KeywordSearchListsAbstract.KeywordSearchList getCurrentKeywordList() {
return currentKeywordList; return currentKeywordList;
} }
void setCurrentKeywordList(KeywordSearchListsAbstract.KeywordSearchList list) { void setCurrentKeywordList(KeywordSearchListsAbstract.KeywordSearchList list) {
currentKeywordList = list; currentKeywordList = list;
} }
void addDeleteButtonActionPerformed(ActionListener l) { void addDeleteButtonActionPerformed(ActionListener l) {
deleteListButton.addActionListener(l); deleteListButton.addActionListener(l);
} }
void addSaveButtonActionPerformed(ActionListener l) { void addSaveButtonActionPerformed(ActionListener l) {
saveListButton.addActionListener(l); saveListButton.addActionListener(l);
} }
@ -698,7 +749,8 @@ private void useForIngestCheckboxActionPerformed(java.awt.event.ActionEvent evt)
colName = NbBundle.getMessage(this.getClass(), "KeywordSearchEditListPanel.kwColName"); colName = NbBundle.getMessage(this.getClass(), "KeywordSearchEditListPanel.kwColName");
break; break;
case 1: case 1:
colName = NbBundle.getMessage(this.getClass(), "KeywordSearchEditListPanel.exportButtonActionPerformed.regExColName"); colName = NbBundle.getMessage(this.getClass(),
"KeywordSearchEditListPanel.exportButtonActionPerformed.regExColName");
break; break;
default: default:
; ;
@ -710,7 +762,7 @@ private void useForIngestCheckboxActionPerformed(java.awt.event.ActionEvent evt)
@Override @Override
public Object getValueAt(int rowIndex, int columnIndex) { public Object getValueAt(int rowIndex, int columnIndex) {
Object ret = null; Object ret = null;
if(currentKeywordList == null) { if (currentKeywordList == null) {
return ""; return "";
} }
Keyword word = currentKeywordList.getKeywords().get(rowIndex); Keyword word = currentKeywordList.getKeywords().get(rowIndex);
@ -743,7 +795,7 @@ private void useForIngestCheckboxActionPerformed(java.awt.event.ActionEvent evt)
} }
void addKeyword(Keyword keyword) { void addKeyword(Keyword keyword) {
if(!currentKeywordList.hasKeyword(keyword)) { if (!currentKeywordList.hasKeyword(keyword)) {
currentKeywordList.getKeywords().add(keyword); currentKeywordList.getKeywords().add(keyword);
} }
fireTableDataChanged(); fireTableDataChanged();
@ -757,7 +809,7 @@ private void useForIngestCheckboxActionPerformed(java.awt.event.ActionEvent evt)
void deleteSelected(int[] selected) { void deleteSelected(int[] selected) {
List<Keyword> words = currentKeywordList.getKeywords(); List<Keyword> words = currentKeywordList.getKeywords();
Arrays.sort(selected); Arrays.sort(selected);
for(int arrayi = selected.length-1; arrayi >= 0; arrayi--) { for (int arrayi = selected.length - 1; arrayi >= 0; arrayi--) {
words.remove(selected[arrayi]); words.remove(selected[arrayi]);
} }
resync(); resync();

View File

@ -21,6 +21,7 @@ package org.sleuthkit.autopsy.keywordsearch;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import javax.swing.Action; import javax.swing.Action;
import org.openide.nodes.FilterNode; import org.openide.nodes.FilterNode;
import org.openide.nodes.Node; import org.openide.nodes.Node;
import org.openide.nodes.Node.Property; import org.openide.nodes.Node.Property;
@ -120,23 +121,29 @@ class KeywordSearchFilterNode extends FilterNode {
public List<Action> visit(File f) { public List<Action> visit(File f) {
return getFileActions(); return getFileActions();
} }
@Override @Override
public List<Action> visit(DerivedFile f) { public List<Action> visit(DerivedFile f) {
return getFileActions(); return getFileActions();
} }
private List<Action> getFileActions() { private List<Action> getFileActions() {
List<Action> actions = new ArrayList<>(); List<Action> actions = new ArrayList<>();
actions.add(new NewWindowViewAction(NbBundle.getMessage(this.getClass(), "KeywordSearchFilterNode.getFileActions.viewInNewWinActionLbl"), KeywordSearchFilterNode.this)); actions.add(new NewWindowViewAction(NbBundle.getMessage(this.getClass(),
actions.add(new ExternalViewerAction(NbBundle.getMessage(this.getClass(), "KeywordSearchFilterNode.getFileActions.openExternViewActLbl"), getOriginal())); "KeywordSearchFilterNode.getFileActions.viewInNewWinActionLbl"),
KeywordSearchFilterNode.this));
actions.add(new ExternalViewerAction(
NbBundle.getMessage(this.getClass(), "KeywordSearchFilterNode.getFileActions.openExternViewActLbl"),
getOriginal()));
actions.add(null); actions.add(null);
actions.add(ExtractAction.getInstance()); actions.add(ExtractAction.getInstance());
actions.add(new HashSearchAction(NbBundle.getMessage(this.getClass(), "KeywordSearchFilterNode.getFileActions.searchSameMd5"), getOriginal())); actions.add(new HashSearchAction(
NbBundle.getMessage(this.getClass(), "KeywordSearchFilterNode.getFileActions.searchSameMd5"),
getOriginal()));
actions.add(null); // creates a menu separator actions.add(null); // creates a menu separator
actions.add(AddContentTagAction.getInstance()); actions.add(AddContentTagAction.getInstance());
actions.addAll(ContextMenuExtensionPoint.getActions()); actions.addAll(ContextMenuExtensionPoint.getActions());
return actions; return actions;
} }
@Override @Override

View File

@ -36,9 +36,11 @@ import java.util.logging.Level;
import org.openide.util.NbBundle; import org.openide.util.NbBundle;
import org.sleuthkit.autopsy.coreutils.Logger; import org.sleuthkit.autopsy.coreutils.Logger;
import javax.swing.SwingUtilities; import javax.swing.SwingUtilities;
import javax.swing.SwingWorker; import javax.swing.SwingWorker;
import javax.swing.Timer; import javax.swing.Timer;
import org.apache.tika.Tika; import org.apache.tika.Tika;
import org.netbeans.api.progress.aggregate.AggregateProgressFactory; import org.netbeans.api.progress.aggregate.AggregateProgressFactory;
import org.netbeans.api.progress.aggregate.AggregateProgressHandle; import org.netbeans.api.progress.aggregate.AggregateProgressHandle;
@ -75,7 +77,7 @@ import org.sleuthkit.datamodel.TskData.FileKnown;
* ingest update interval) Runs a periodic keyword / regular expression search * ingest update interval) Runs a periodic keyword / regular expression search
* on currently configured lists for ingest and writes results to blackboard * on currently configured lists for ingest and writes results to blackboard
* Reports interesting events to Inbox and to viewers * Reports interesting events to Inbox and to viewers
* * <p/>
* Registered as a module in layer.xml * Registered as a module in layer.xml
*/ */
public final class KeywordSearchIngestModule extends IngestModuleAbstractFile { public final class KeywordSearchIngestModule extends IngestModuleAbstractFile {
@ -96,10 +98,13 @@ public final class KeywordSearchIngestModule extends IngestModuleAbstractFile {
int getTime() { int getTime() {
return time; return time;
} }
}; }
;
private static final Logger logger = Logger.getLogger(KeywordSearchIngestModule.class.getName()); private static final Logger logger = Logger.getLogger(KeywordSearchIngestModule.class.getName());
public static final String MODULE_NAME = "Keyword Search"; public static final String MODULE_NAME = "Keyword Search";
public static final String MODULE_DESCRIPTION = "Performs file indexing and periodic search using keywords and regular expressions in lists."; public static final String MODULE_DESCRIPTION
= "Performs file indexing and periodic search using keywords and regular expressions in lists.";
final public static String MODULE_VERSION = Version.getVersion(); final public static String MODULE_VERSION = Version.getVersion();
private static KeywordSearchIngestModule instance = null; private static KeywordSearchIngestModule instance = null;
private IngestServices services; private IngestServices services;
@ -132,7 +137,7 @@ public final class KeywordSearchIngestModule extends IngestModuleAbstractFile {
private KeywordSearchIngestSimplePanel simpleConfigPanel; private KeywordSearchIngestSimplePanel simpleConfigPanel;
private KeywordSearchConfigurationPanel advancedConfigPanel; private KeywordSearchConfigurationPanel advancedConfigPanel;
private Tika tikaFormatDetector; private Tika tikaFormatDetector;
private enum IngestStatus { private enum IngestStatus {
TEXT_INGESTED, /// Text was extracted by knowing file type and text_ingested TEXT_INGESTED, /// Text was extracted by knowing file type and text_ingested
@ -141,7 +146,9 @@ public final class KeywordSearchIngestModule extends IngestModuleAbstractFile {
SKIPPED_ERROR_INDEXING, ///< File was skipped because index engine had problems SKIPPED_ERROR_INDEXING, ///< File was skipped because index engine had problems
SKIPPED_ERROR_TEXTEXTRACT, ///< File was skipped because of text extraction issues SKIPPED_ERROR_TEXTEXTRACT, ///< File was skipped because of text extraction issues
SKIPPED_ERROR_IO ///< File was skipped because of IO issues reading it SKIPPED_ERROR_IO ///< File was skipped because of IO issues reading it
}; }
;
private Map<Long, IngestStatus> ingestStatus; private Map<Long, IngestStatus> ingestStatus;
//private constructor to ensure singleton instance //private constructor to ensure singleton instance
@ -175,9 +182,10 @@ public final class KeywordSearchIngestModule extends IngestModuleAbstractFile {
curDataSourceIds.add(fileSourceId); curDataSourceIds.add(fileSourceId);
} catch (TskCoreException ex) { } catch (TskCoreException ex) {
logger.log(Level.SEVERE, "Error getting image id of file processed by keyword search: " + abstractFile.getName(), ex); logger.log(Level.SEVERE,
"Error getting image id of file processed by keyword search: " + abstractFile.getName(), ex);
} }
if (abstractFile.getType().equals(TskData.TSK_DB_FILES_TYPE_ENUM.VIRTUAL_DIR)) { if (abstractFile.getType().equals(TskData.TSK_DB_FILES_TYPE_ENUM.VIRTUAL_DIR)) {
//skip indexing of virtual dirs (no content, no real name) - will index children files //skip indexing of virtual dirs (no content, no real name) - will index children files
return ProcessResult.OK; return ProcessResult.OK;
@ -189,14 +197,13 @@ public final class KeywordSearchIngestModule extends IngestModuleAbstractFile {
//notify depending module that keyword search (would) encountered error for this file //notify depending module that keyword search (would) encountered error for this file
ingestStatus.put(abstractFile.getId(), IngestStatus.SKIPPED_ERROR_IO); ingestStatus.put(abstractFile.getId(), IngestStatus.SKIPPED_ERROR_IO);
return ProcessResult.ERROR; return ProcessResult.ERROR;
} } else if (KeywordSearchSettings.getSkipKnown() && abstractFile.getKnown().equals(FileKnown.KNOWN)) {
else if (KeywordSearchSettings.getSkipKnown() && abstractFile.getKnown().equals(FileKnown.KNOWN)) {
//index meta-data only //index meta-data only
indexer.indexFile(abstractFile, false); indexer.indexFile(abstractFile, false);
return ProcessResult.OK; return ProcessResult.OK;
} }
processedFiles = true; processedFiles = true;
//check if it's time to commit after previous processing //check if it's time to commit after previous processing
checkRunCommitSearch(); checkRunCommitSearch();
@ -337,7 +344,6 @@ public final class KeywordSearchIngestModule extends IngestModuleAbstractFile {
/** /**
* Initializes the module for new ingest run Sets up threads, timers, * Initializes the module for new ingest run Sets up threads, timers,
* retrieves settings, keyword lists to run on * retrieves settings, keyword lists to run on
*
*/ */
@Override @Override
public void init(IngestModuleInit initContext) { public void init(IngestModuleInit initContext) {
@ -356,7 +362,8 @@ public final class KeywordSearchIngestModule extends IngestModuleAbstractFile {
if (!server.isRunning()) { if (!server.isRunning()) {
String msg = NbBundle.getMessage(this.getClass(), "KeywordSearchIngestModule.init.badInitMsg"); String msg = NbBundle.getMessage(this.getClass(), "KeywordSearchIngestModule.init.badInitMsg");
logger.log(Level.SEVERE, msg); logger.log(Level.SEVERE, msg);
String details = NbBundle.getMessage(this.getClass(), "KeywordSearchIngestModule.init.tryStopSolrMsg", msg); String details = NbBundle
.getMessage(this.getClass(), "KeywordSearchIngestModule.init.tryStopSolrMsg", msg);
services.postMessage(IngestMessage.createErrorMessage(++messageID, instance, msg, details)); services.postMessage(IngestMessage.createErrorMessage(++messageID, instance, msg, details));
return; return;
@ -399,8 +406,11 @@ public final class KeywordSearchIngestModule extends IngestModuleAbstractFile {
initKeywords(); initKeywords();
if (keywords.isEmpty() || keywordLists.isEmpty()) { if (keywords.isEmpty() || keywordLists.isEmpty()) {
services.postMessage(IngestMessage.createWarningMessage(++messageID, instance, NbBundle.getMessage(this.getClass(), "KeywordSearchIngestModule.init.noKwInLstMsg"), services.postMessage(IngestMessage.createWarningMessage(++messageID, instance,
NbBundle.getMessage(this.getClass(), "KeywordSearchIngestModule.init.onlyIdxKwSkipMsg"))); NbBundle.getMessage(this.getClass(),
"KeywordSearchIngestModule.init.noKwInLstMsg"),
NbBundle.getMessage(this.getClass(),
"KeywordSearchIngestModule.init.onlyIdxKwSkipMsg")));
} }
processedFiles = false; processedFiles = false;
@ -439,14 +449,13 @@ public final class KeywordSearchIngestModule extends IngestModuleAbstractFile {
@Override @Override
public javax.swing.JPanel getSimpleConfiguration(String context) { public javax.swing.JPanel getSimpleConfiguration(String context) {
KeywordSearchListsXML.getCurrent().reload(); KeywordSearchListsXML.getCurrent().reload();
if (null == simpleConfigPanel) { if (null == simpleConfigPanel) {
simpleConfigPanel = new KeywordSearchIngestSimplePanel(); simpleConfigPanel = new KeywordSearchIngestSimplePanel();
} } else {
else {
simpleConfigPanel.load(); simpleConfigPanel.load();
} }
return simpleConfigPanel; return simpleConfigPanel;
} }
@ -455,7 +464,7 @@ public final class KeywordSearchIngestModule extends IngestModuleAbstractFile {
if (advancedConfigPanel == null) { if (advancedConfigPanel == null) {
advancedConfigPanel = new KeywordSearchConfigurationPanel(); advancedConfigPanel = new KeywordSearchConfigurationPanel();
} }
advancedConfigPanel.load(); advancedConfigPanel.load();
return advancedConfigPanel; return advancedConfigPanel;
} }
@ -465,7 +474,7 @@ public final class KeywordSearchIngestModule extends IngestModuleAbstractFile {
if (advancedConfigPanel != null) { if (advancedConfigPanel != null) {
advancedConfigPanel.store(); advancedConfigPanel.store();
} }
if (simpleConfigPanel != null) { if (simpleConfigPanel != null) {
simpleConfigPanel.load(); simpleConfigPanel.load();
} }
@ -543,23 +552,42 @@ public final class KeywordSearchIngestModule extends IngestModuleAbstractFile {
} }
StringBuilder msg = new StringBuilder(); StringBuilder msg = new StringBuilder();
msg.append("<table border=0><tr><td>").append(NbBundle.getMessage(this.getClass(), "KeywordSearchIngestModule.postIndexSummary.knowFileHeaderLbl")).append("</td><td>").append(text_ingested).append("</td></tr>"); msg.append("<table border=0><tr><td>")
msg.append("<tr><td>").append(NbBundle.getMessage(this.getClass(), "KeywordSearchIngestModule.postIndexSummary.fileGenStringsHead")).append("</td><td>").append(strings_ingested).append("</td></tr>"); .append(NbBundle.getMessage(this.getClass(), "KeywordSearchIngestModule.postIndexSummary.knowFileHeaderLbl"))
msg.append("<tr><td>").append(NbBundle.getMessage(this.getClass(), "KeywordSearchIngestModule.postIndexSummary.mdOnlyLbl")).append("</td><td>").append(metadata_ingested).append("</td></tr>"); .append("</td><td>").append(text_ingested).append("</td></tr>");
msg.append("<tr><td>").append(NbBundle.getMessage(this.getClass(), "KeywordSearchIngestModule.postIndexSummary.idxErrLbl")).append("</td><td>").append(error_index).append("</td></tr>"); msg.append("<tr><td>").append(NbBundle.getMessage(this.getClass(),
msg.append("<tr><td>").append(NbBundle.getMessage(this.getClass(), "KeywordSearchIngestModule.postIndexSummary.errTxtLbl")).append("</td><td>").append(error_text).append("</td></tr>"); "KeywordSearchIngestModule.postIndexSummary.fileGenStringsHead"))
msg.append("<tr><td>").append(NbBundle.getMessage(this.getClass(), "KeywordSearchIngestModule.postIndexSummary.errIoLbl")).append("</td><td>").append(error_io).append("</td></tr>"); .append("</td><td>").append(strings_ingested).append("</td></tr>");
msg.append("<tr><td>")
.append(NbBundle.getMessage(this.getClass(), "KeywordSearchIngestModule.postIndexSummary.mdOnlyLbl"))
.append("</td><td>").append(metadata_ingested).append("</td></tr>");
msg.append("<tr><td>")
.append(NbBundle.getMessage(this.getClass(), "KeywordSearchIngestModule.postIndexSummary.idxErrLbl"))
.append("</td><td>").append(error_index).append("</td></tr>");
msg.append("<tr><td>")
.append(NbBundle.getMessage(this.getClass(), "KeywordSearchIngestModule.postIndexSummary.errTxtLbl"))
.append("</td><td>").append(error_text).append("</td></tr>");
msg.append("<tr><td>")
.append(NbBundle.getMessage(this.getClass(), "KeywordSearchIngestModule.postIndexSummary.errIoLbl"))
.append("</td><td>").append(error_io).append("</td></tr>");
msg.append("</table>"); msg.append("</table>");
String indexStats = msg.toString(); String indexStats = msg.toString();
logger.log(Level.INFO, "Keyword Indexing Completed: " + indexStats); logger.log(Level.INFO, "Keyword Indexing Completed: " + indexStats);
services.postMessage(IngestMessage.createMessage(++messageID, MessageType.INFO, this, NbBundle.getMessage(this.getClass(), "KeywordSearchIngestModule.postIndexSummary.kwIdxResultsLbl"), indexStats)); services.postMessage(IngestMessage.createMessage(++messageID, MessageType.INFO, this,
NbBundle.getMessage(this.getClass(),
"KeywordSearchIngestModule.postIndexSummary.kwIdxResultsLbl"),
indexStats));
if (error_index > 0) { if (error_index > 0) {
MessageNotifyUtil.Notify.error(NbBundle.getMessage(this.getClass(), "KeywordSearchIngestModule.postIndexSummary.kwIdxErrsTitle"), MessageNotifyUtil.Notify.error(NbBundle.getMessage(this.getClass(),
NbBundle.getMessage(this.getClass(), "KeywordSearchIngestModule.postIndexSummary.kwIdxErrMsgFiles", error_index)); "KeywordSearchIngestModule.postIndexSummary.kwIdxErrsTitle"),
} NbBundle.getMessage(this.getClass(),
else if (error_io + error_text > 0) { "KeywordSearchIngestModule.postIndexSummary.kwIdxErrMsgFiles",
MessageNotifyUtil.Notify.warn(NbBundle.getMessage(this.getClass(), "KeywordSearchIngestModule.postIndexSummary.kwIdxWarnMsgTitle"), error_index));
NbBundle.getMessage(this.getClass(), "KeywordSearchIngestModule.postIndexSummary.idxErrReadFilesMsg")); } else if (error_io + error_text > 0) {
MessageNotifyUtil.Notify.warn(NbBundle.getMessage(this.getClass(),
"KeywordSearchIngestModule.postIndexSummary.kwIdxWarnMsgTitle"),
NbBundle.getMessage(this.getClass(),
"KeywordSearchIngestModule.postIndexSummary.idxErrReadFilesMsg"));
} }
} }
@ -695,8 +723,8 @@ public final class KeywordSearchIngestModule extends IngestModuleAbstractFile {
* streaming) from the file Divide the file into chunks and index the * streaming) from the file Divide the file into chunks and index the
* chunks * chunks
* *
* @param aFile file to extract strings from, divide into chunks and * @param aFile file to extract strings from, divide into chunks and
* index * index
* @param detectedFormat mime-type detected, or null if none detected * @param detectedFormat mime-type detected, or null if none detected
* @return true if the file was text_ingested, false otherwise * @return true if the file was text_ingested, false otherwise
* @throws IngesterException exception thrown if indexing failed * @throws IngesterException exception thrown if indexing failed
@ -728,7 +756,7 @@ public final class KeywordSearchIngestModule extends IngestModuleAbstractFile {
* Extract strings using heuristics from the file and add to index. * Extract strings using heuristics from the file and add to index.
* *
* @param aFile file to extract strings from, divide into chunks and * @param aFile file to extract strings from, divide into chunks and
* index * index
* @return true if the file was text_ingested, false otherwise * @return true if the file was text_ingested, false otherwise
*/ */
private boolean extractStringsAndIndex(AbstractFile aFile) { private boolean extractStringsAndIndex(AbstractFile aFile) {
@ -737,12 +765,16 @@ public final class KeywordSearchIngestModule extends IngestModuleAbstractFile {
ingestStatus.put(aFile.getId(), IngestStatus.STRINGS_INGESTED); ingestStatus.put(aFile.getId(), IngestStatus.STRINGS_INGESTED);
return true; return true;
} else { } else {
logger.log(Level.WARNING, "Failed to extract strings and ingest, file '" + aFile.getName() + "' (id: " + aFile.getId() + ")."); logger.log(Level.WARNING,
"Failed to extract strings and ingest, file '" + aFile.getName() + "' (id: " + aFile
.getId() + ").");
ingestStatus.put(aFile.getId(), IngestStatus.SKIPPED_ERROR_TEXTEXTRACT); ingestStatus.put(aFile.getId(), IngestStatus.SKIPPED_ERROR_TEXTEXTRACT);
return false; return false;
} }
} catch (IngesterException ex) { } catch (IngesterException ex) {
logger.log(Level.WARNING, "Failed to extract strings and ingest, file '" + aFile.getName() + "' (id: " + aFile.getId() + ").", ex); logger.log(Level.WARNING,
"Failed to extract strings and ingest, file '" + aFile.getName() + "' (id: " + aFile.getId()
+ ").", ex);
ingestStatus.put(aFile.getId(), IngestStatus.SKIPPED_ERROR_INDEXING); ingestStatus.put(aFile.getId(), IngestStatus.SKIPPED_ERROR_INDEXING);
return false; return false;
} }
@ -752,9 +784,9 @@ public final class KeywordSearchIngestModule extends IngestModuleAbstractFile {
* Check with every extractor if it supports the file with the detected * Check with every extractor if it supports the file with the detected
* format * format
* *
* @param aFile file to check for * @param aFile file to check for
* @param detectedFormat mime-type with detected format (such as * @param detectedFormat mime-type with detected format (such as
* text/plain) or null if not detected * text/plain) or null if not detected
* @return true if text extraction is supported * @return true if text extraction is supported
*/ */
private boolean isTextExtractSupported(AbstractFile aFile, String detectedFormat) { private boolean isTextExtractSupported(AbstractFile aFile, String detectedFormat) {
@ -770,17 +802,18 @@ public final class KeywordSearchIngestModule extends IngestModuleAbstractFile {
/** /**
* Adds the file to the index. Detects file type, calls extractors, etc. * Adds the file to the index. Detects file type, calls extractors, etc.
* *
* @param aFile File to analyze * @param aFile File to analyze
* @param indexContent False if only metadata should be text_ingested. True if * @param indexContent False if only metadata should be text_ingested. True if
* content and metadata should be index. * content and metadata should be index.
*/ */
private void indexFile(AbstractFile aFile, boolean indexContent) { private void indexFile(AbstractFile aFile, boolean indexContent) {
//logger.log(Level.INFO, "Processing AbstractFile: " + abstractFile.getName()); //logger.log(Level.INFO, "Processing AbstractFile: " + abstractFile.getName());
TskData.TSK_DB_FILES_TYPE_ENUM aType = aFile.getType(); TskData.TSK_DB_FILES_TYPE_ENUM aType = aFile.getType();
// unallocated and unused blocks can only have strings extracted from them. // unallocated and unused blocks can only have strings extracted from them.
if ((aType.equals(TskData.TSK_DB_FILES_TYPE_ENUM.UNALLOC_BLOCKS) || aType.equals(TskData.TSK_DB_FILES_TYPE_ENUM.UNUSED_BLOCKS))) { if ((aType.equals(TskData.TSK_DB_FILES_TYPE_ENUM.UNALLOC_BLOCKS) || aType
.equals(TskData.TSK_DB_FILES_TYPE_ENUM.UNUSED_BLOCKS))) {
extractStringsAndIndex(aFile); extractStringsAndIndex(aFile);
} }
@ -790,8 +823,7 @@ public final class KeywordSearchIngestModule extends IngestModuleAbstractFile {
try { try {
ingester.ingest(aFile, false); //meta-data only ingester.ingest(aFile, false); //meta-data only
ingestStatus.put(aFile.getId(), IngestStatus.METADATA_INGESTED); ingestStatus.put(aFile.getId(), IngestStatus.METADATA_INGESTED);
} } catch (IngesterException ex) {
catch (IngesterException ex) {
ingestStatus.put(aFile.getId(), IngestStatus.SKIPPED_ERROR_INDEXING); ingestStatus.put(aFile.getId(), IngestStatus.SKIPPED_ERROR_INDEXING);
logger.log(Level.WARNING, "Unable to index meta-data for file: " + aFile.getId(), ex); logger.log(Level.WARNING, "Unable to index meta-data for file: " + aFile.getId(), ex);
} }
@ -804,11 +836,9 @@ public final class KeywordSearchIngestModule extends IngestModuleAbstractFile {
try { try {
is = new ReadContentInputStream(aFile); is = new ReadContentInputStream(aFile);
detectedFormat = tikaFormatDetector.detect(is, aFile.getName()); detectedFormat = tikaFormatDetector.detect(is, aFile.getName());
} } catch (Exception e) {
catch (Exception e) {
logger.log(Level.WARNING, "Could not detect format using tika for file: " + aFile, e); logger.log(Level.WARNING, "Could not detect format using tika for file: " + aFile, e);
} } finally {
finally {
if (is != null) { if (is != null) {
try { try {
is.close(); is.close();
@ -818,9 +848,9 @@ public final class KeywordSearchIngestModule extends IngestModuleAbstractFile {
} }
} }
} }
// @@@ Add file type signature to blackboard here // @@@ Add file type signature to blackboard here
//logger.log(Level.INFO, "Detected format: " + aFile.getName() + " " + detectedFormat); //logger.log(Level.INFO, "Detected format: " + aFile.getName() + " " + detectedFormat);
// we skip archive formats that are opened by the archive module. // we skip archive formats that are opened by the archive module.
@ -829,8 +859,7 @@ public final class KeywordSearchIngestModule extends IngestModuleAbstractFile {
try { try {
ingester.ingest(aFile, false); //meta-data only ingester.ingest(aFile, false); //meta-data only
ingestStatus.put(aFile.getId(), IngestStatus.METADATA_INGESTED); ingestStatus.put(aFile.getId(), IngestStatus.METADATA_INGESTED);
} } catch (IngesterException ex) {
catch (IngesterException ex) {
ingestStatus.put(aFile.getId(), IngestStatus.SKIPPED_ERROR_INDEXING); ingestStatus.put(aFile.getId(), IngestStatus.SKIPPED_ERROR_INDEXING);
logger.log(Level.WARNING, "Unable to index meta-data for file: " + aFile.getId(), ex); logger.log(Level.WARNING, "Unable to index meta-data for file: " + aFile.getId(), ex);
} }
@ -843,7 +872,9 @@ public final class KeywordSearchIngestModule extends IngestModuleAbstractFile {
try { try {
//logger.log(Level.INFO, "indexing: " + aFile.getName()); //logger.log(Level.INFO, "indexing: " + aFile.getName());
if (!extractTextAndIndex(aFile, detectedFormat)) { if (!extractTextAndIndex(aFile, detectedFormat)) {
logger.log(Level.WARNING, "Failed to extract text and ingest, file '" + aFile.getName() + "' (id: " + aFile.getId() + ")."); logger.log(Level.WARNING,
"Failed to extract text and ingest, file '" + aFile.getName() + "' (id: " + aFile
.getId() + ").");
ingestStatus.put(aFile.getId(), IngestStatus.SKIPPED_ERROR_TEXTEXTRACT); ingestStatus.put(aFile.getId(), IngestStatus.SKIPPED_ERROR_TEXTEXTRACT);
} else { } else {
ingestStatus.put(aFile.getId(), IngestStatus.TEXT_INGESTED); ingestStatus.put(aFile.getId(), IngestStatus.TEXT_INGESTED);
@ -906,15 +937,21 @@ public final class KeywordSearchIngestModule extends IngestModuleAbstractFile {
logger.log(Level.INFO, "Pending start of new searcher"); logger.log(Level.INFO, "Pending start of new searcher");
} }
final String displayName = NbBundle.getMessage(this.getClass(), "KeywordSearchIngestModule.doInBackGround.displayName") + final String displayName =
(finalRun ? (" - "+ NbBundle.getMessage(this.getClass(), "KeywordSearchIngestModule.doInBackGround.finalizeMsg")) : ""); NbBundle.getMessage(this.getClass(), "KeywordSearchIngestModule.doInBackGround.displayName") +
progressGroup = AggregateProgressFactory.createSystemHandle(displayName + (" ("+ (finalRun ? (" - " + NbBundle.getMessage(this.getClass(),
NbBundle.getMessage(this.getClass(), "KeywordSearchIngestModule.doInBackGround.pendingMsg") +")"), null, new Cancellable() { "KeywordSearchIngestModule.doInBackGround.finalizeMsg"))
: "");
progressGroup = AggregateProgressFactory.createSystemHandle(displayName + (" (" +
NbBundle.getMessage(this.getClass(), "KeywordSearchIngestModule.doInBackGround.pendingMsg") + ")"),
null, new Cancellable() {
@Override @Override
public boolean cancel() { public boolean cancel() {
logger.log(Level.INFO, "Cancelling the searcher by user."); logger.log(Level.INFO, "Cancelling the searcher by user.");
if (progressGroup != null) { if (progressGroup != null) {
progressGroup.setDisplayName(displayName + " ("+ NbBundle.getMessage(this.getClass(), "KeywordSearchIngestModule.doInBackGround.cancelMsg") +"...)"); progressGroup.setDisplayName(displayName + " (" + NbBundle
.getMessage(this.getClass(), "KeywordSearchIngestModule.doInBackGround.cancelMsg")
+ "...)");
} }
return Searcher.this.cancel(true); return Searcher.this.cancel(true);
} }
@ -954,7 +991,8 @@ public final class KeywordSearchIngestModule extends IngestModuleAbstractFile {
for (Keyword keywordQuery : keywords) { for (Keyword keywordQuery : keywords) {
if (this.isCancelled()) { if (this.isCancelled()) {
logger.log(Level.INFO, "Cancel detected, bailing before new keyword processed: " + keywordQuery.getQuery()); logger.log(Level.INFO,
"Cancel detected, bailing before new keyword processed: " + keywordQuery.getQuery());
return null; return null;
} }
@ -974,15 +1012,15 @@ public final class KeywordSearchIngestModule extends IngestModuleAbstractFile {
boolean isRegex = !keywordQuery.isLiteral(); boolean isRegex = !keywordQuery.isLiteral();
if (isRegex) { if (isRegex) {
del = new TermComponentQuery(keywordQuery); del = new TermComponentQuery(keywordQuery);
} } else {
else {
del = new LuceneQuery(keywordQuery); del = new LuceneQuery(keywordQuery);
del.escape(); del.escape();
} }
//limit search to currently ingested data sources //limit search to currently ingested data sources
//set up a filter with 1 or more image ids OR'ed //set up a filter with 1 or more image ids OR'ed
final KeywordQueryFilter dataSourceFilter = new KeywordQueryFilter(KeywordQueryFilter.FilterType.DATA_SOURCE, curDataSourceIds); final KeywordQueryFilter dataSourceFilter = new KeywordQueryFilter(
KeywordQueryFilter.FilterType.DATA_SOURCE, curDataSourceIds);
del.addFilter(dataSourceFilter); del.addFilter(dataSourceFilter);
Map<String, List<ContentHit>> queryResult = null; Map<String, List<ContentHit>> queryResult = null;
@ -996,7 +1034,8 @@ public final class KeywordSearchIngestModule extends IngestModuleAbstractFile {
//likely case has closed and threads are being interrupted //likely case has closed and threads are being interrupted
return null; return null;
} catch (CancellationException e) { } catch (CancellationException e) {
logger.log(Level.INFO, "Cancel detected, bailing during keyword query: " + keywordQuery.getQuery()); logger.log(Level.INFO,
"Cancel detected, bailing during keyword query: " + keywordQuery.getQuery());
return null; return null;
} catch (Exception e) { } catch (Exception e) {
logger.log(Level.WARNING, "Error performing query: " + keywordQuery.getQuery(), e); logger.log(Level.WARNING, "Error performing query: " + keywordQuery.getQuery(), e);
@ -1029,10 +1068,11 @@ public final class KeywordSearchIngestModule extends IngestModuleAbstractFile {
for (final Keyword hitTerm : newResults.keySet()) { for (final Keyword hitTerm : newResults.keySet()) {
//checking for cancellation between results //checking for cancellation between results
if (this.isCancelled()) { if (this.isCancelled()) {
logger.log(Level.INFO, "Cancel detected, bailing before new hit processed for query: " + keywordQuery.getQuery()); logger.log(Level.INFO, "Cancel detected, bailing before new hit processed for query: "
+ keywordQuery.getQuery());
return null; return null;
} }
// update progress display // update progress display
String hitDisplayStr = hitTerm.getQuery(); String hitDisplayStr = hitTerm.getQuery();
if (hitDisplayStr.length() > 50) { if (hitDisplayStr.length() > 50) {
@ -1042,15 +1082,17 @@ public final class KeywordSearchIngestModule extends IngestModuleAbstractFile {
//subProgresses[keywordsSearched].progress(unitProgress); //subProgresses[keywordsSearched].progress(unitProgress);
// this returns the unique files in the set with the first chunk that has a hit // this returns the unique files in the set with the first chunk that has a hit
Map<AbstractFile, Integer> contentHitsFlattened = ContentHit.flattenResults(newResults.get(hitTerm)); Map<AbstractFile, Integer> contentHitsFlattened = ContentHit
.flattenResults(newResults.get(hitTerm));
for (final AbstractFile hitFile : contentHitsFlattened.keySet()) { for (final AbstractFile hitFile : contentHitsFlattened.keySet()) {
// get the snippet for the first hit in the file // get the snippet for the first hit in the file
String snippet = null; String snippet = null;
final String snippetQuery = KeywordSearchUtil.escapeLuceneQuery(hitTerm.getQuery()); final String snippetQuery = KeywordSearchUtil.escapeLuceneQuery(hitTerm.getQuery());
int chunkId = contentHitsFlattened.get(hitFile); int chunkId = contentHitsFlattened.get(hitFile);
try { try {
snippet = LuceneQuery.querySnippet(snippetQuery, hitFile.getId(), chunkId, isRegex, true); snippet = LuceneQuery
.querySnippet(snippetQuery, hitFile.getId(), chunkId, isRegex, true);
} catch (NoOpenCoreException e) { } catch (NoOpenCoreException e) {
logger.log(Level.WARNING, "Error querying snippet: " + snippetQuery, e); logger.log(Level.WARNING, "Error querying snippet: " + snippetQuery, e);
//no reason to continue //no reason to continue
@ -1061,9 +1103,12 @@ public final class KeywordSearchIngestModule extends IngestModuleAbstractFile {
} }
// write the blackboard artifact for this keyword in this file // write the blackboard artifact for this keyword in this file
KeywordWriteResult written = del.writeToBlackBoard(hitTerm.getQuery(), hitFile, snippet, listName); KeywordWriteResult written = del
.writeToBlackBoard(hitTerm.getQuery(), hitFile, snippet, listName);
if (written == null) { if (written == null) {
logger.log(Level.WARNING, "BB artifact for keyword hit not written, file: " + hitFile + ", hit: " + hitTerm.toString()); logger.log(Level.WARNING,
"BB artifact for keyword hit not written, file: " + hitFile + ", hit: "
+ hitTerm.toString());
continue; continue;
} }
@ -1076,13 +1121,16 @@ public final class KeywordSearchIngestModule extends IngestModuleAbstractFile {
//final int hitFiles = newResults.size(); //final int hitFiles = newResults.size();
if (!keywordQuery.isLiteral()) { if (!keywordQuery.isLiteral()) {
subjectSb.append(NbBundle.getMessage(this.getClass(), "KeywordSearchIngestModule.regExpHitLbl")); subjectSb.append(NbBundle.getMessage(this.getClass(),
"KeywordSearchIngestModule.regExpHitLbl"));
} else { } else {
subjectSb.append(NbBundle.getMessage(this.getClass(), "KeywordSearchIngestModule.kwHitLbl")); subjectSb.append(NbBundle.getMessage(this.getClass(),
"KeywordSearchIngestModule.kwHitLbl"));
} }
//subjectSb.append("<"); //subjectSb.append("<");
String uniqueKey = null; String uniqueKey = null;
BlackboardAttribute attr = written.getAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_KEYWORD.getTypeID()); BlackboardAttribute attr = written
.getAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_KEYWORD.getTypeID());
if (attr != null) { if (attr != null) {
final String keyword = attr.getValueString(); final String keyword = attr.getValueString();
subjectSb.append(keyword); subjectSb.append(keyword);
@ -1096,49 +1144,64 @@ public final class KeywordSearchIngestModule extends IngestModuleAbstractFile {
detailsSb.append("<table border='0' cellpadding='4' width='280'>"); detailsSb.append("<table border='0' cellpadding='4' width='280'>");
//hit //hit
detailsSb.append("<tr>"); detailsSb.append("<tr>");
detailsSb.append(NbBundle.getMessage(this.getClass(), "KeywordSearchIngestModule.kwHitLThLbl")); detailsSb.append(NbBundle.getMessage(this.getClass(),
detailsSb.append("<td>").append(EscapeUtil.escapeHtml(attr.getValueString())).append("</td>"); "KeywordSearchIngestModule.kwHitLThLbl"));
detailsSb.append("<td>").append(EscapeUtil.escapeHtml(attr.getValueString()))
.append("</td>");
detailsSb.append("</tr>"); detailsSb.append("</tr>");
//preview //preview
attr = written.getAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_KEYWORD_PREVIEW.getTypeID()); attr = written.getAttribute(
BlackboardAttribute.ATTRIBUTE_TYPE.TSK_KEYWORD_PREVIEW.getTypeID());
if (attr != null) { if (attr != null) {
detailsSb.append("<tr>"); detailsSb.append("<tr>");
detailsSb.append(NbBundle.getMessage(this.getClass(), "KeywordSearchIngestModule.previewThLbl")); detailsSb.append(NbBundle.getMessage(this.getClass(),
detailsSb.append("<td>").append(EscapeUtil.escapeHtml(attr.getValueString())).append("</td>"); "KeywordSearchIngestModule.previewThLbl"));
detailsSb.append("<td>").append(EscapeUtil.escapeHtml(attr.getValueString()))
.append("</td>");
detailsSb.append("</tr>"); detailsSb.append("</tr>");
} }
//file //file
detailsSb.append("<tr>"); detailsSb.append("<tr>");
detailsSb.append(NbBundle.getMessage(this.getClass(), "KeywordSearchIngestModule.fileThLbl")); detailsSb.append(NbBundle.getMessage(this.getClass(),
detailsSb.append("<td>").append(hitFile.getParentPath()).append(hitFile.getName()).append("</td>"); "KeywordSearchIngestModule.fileThLbl"));
detailsSb.append("<td>").append(hitFile.getParentPath()).append(hitFile.getName())
.append("</td>");
detailsSb.append("</tr>"); detailsSb.append("</tr>");
//list //list
attr = written.getAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_SET_NAME.getTypeID()); attr = written
.getAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_SET_NAME.getTypeID());
detailsSb.append("<tr>"); detailsSb.append("<tr>");
detailsSb.append(NbBundle.getMessage(this.getClass(), "KeywordSearchIngestModule.listThLbl")); detailsSb.append(NbBundle.getMessage(this.getClass(),
"KeywordSearchIngestModule.listThLbl"));
detailsSb.append("<td>").append(attr.getValueString()).append("</td>"); detailsSb.append("<td>").append(attr.getValueString()).append("</td>");
detailsSb.append("</tr>"); detailsSb.append("</tr>");
//regex //regex
if (!keywordQuery.isLiteral()) { if (!keywordQuery.isLiteral()) {
attr = written.getAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_KEYWORD_REGEXP.getTypeID()); attr = written.getAttribute(
BlackboardAttribute.ATTRIBUTE_TYPE.TSK_KEYWORD_REGEXP.getTypeID());
if (attr != null) { if (attr != null) {
detailsSb.append("<tr>"); detailsSb.append("<tr>");
detailsSb.append(NbBundle.getMessage(this.getClass(), "KeywordSearchIngestModule.regExThLbl")); detailsSb.append(NbBundle.getMessage(this.getClass(),
"KeywordSearchIngestModule.regExThLbl"));
detailsSb.append("<td>").append(attr.getValueString()).append("</td>"); detailsSb.append("<td>").append(attr.getValueString()).append("</td>");
detailsSb.append("</tr>"); detailsSb.append("</tr>");
} }
} }
detailsSb.append("</table>"); detailsSb.append("</table>");
services.postMessage(IngestMessage.createDataMessage(++messageID, instance, subjectSb.toString(), detailsSb.toString(), uniqueKey, written.getArtifact())); services.postMessage(IngestMessage.createDataMessage(++messageID, instance,
subjectSb.toString(),
detailsSb.toString(),
uniqueKey,
written.getArtifact()));
} }
} //for each file hit } //for each file hit
@ -1148,7 +1211,8 @@ public final class KeywordSearchIngestModule extends IngestModuleAbstractFile {
//update artifact browser //update artifact browser
if (!newArtifacts.isEmpty()) { if (!newArtifacts.isEmpty()) {
services.fireModuleDataEvent(new ModuleDataEvent(MODULE_NAME, ARTIFACT_TYPE.TSK_KEYWORD_HIT, newArtifacts)); services.fireModuleDataEvent(
new ModuleDataEvent(MODULE_NAME, ARTIFACT_TYPE.TSK_KEYWORD_HIT, newArtifacts));
} }
} //if has results } //if has results
@ -1198,6 +1262,7 @@ public final class KeywordSearchIngestModule extends IngestModuleAbstractFile {
//perform all essential cleanup that needs to be done right AFTER doInBackground() returns //perform all essential cleanup that needs to be done right AFTER doInBackground() returns
//without relying on done() method that is not guaranteed to run after background thread completes //without relying on done() method that is not guaranteed to run after background thread completes
//NEED to call this method always right before doInBackground() returns //NEED to call this method always right before doInBackground() returns
/** /**
* Performs the cleanup that needs to be done right AFTER * Performs the cleanup that needs to be done right AFTER
* doInBackground() returns without relying on done() method that is not * doInBackground() returns without relying on done() method that is not
@ -1235,7 +1300,8 @@ public final class KeywordSearchIngestModule extends IngestModuleAbstractFile {
//calculate new results but substracting results already obtained in this ingest //calculate new results but substracting results already obtained in this ingest
//update currentResults map with the new results //update currentResults map with the new results
private Map<Keyword, List<ContentHit>> filterResults(Map<String, List<ContentHit>> queryResult, boolean isRegex) { private Map<Keyword, List<ContentHit>> filterResults(Map<String, List<ContentHit>> queryResult,
boolean isRegex) {
Map<Keyword, List<ContentHit>> newResults = new HashMap<Keyword, List<ContentHit>>(); Map<Keyword, List<ContentHit>> newResults = new HashMap<Keyword, List<ContentHit>>();
for (String termResult : queryResult.keySet()) { for (String termResult : queryResult.keySet()) {

View File

@ -23,23 +23,28 @@ package org.sleuthkit.autopsy.keywordsearch;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import javax.swing.JTable; import javax.swing.JTable;
import org.sleuthkit.autopsy.coreutils.Logger; import org.sleuthkit.autopsy.coreutils.Logger;
import javax.swing.ListSelectionModel; import javax.swing.ListSelectionModel;
import javax.swing.table.AbstractTableModel; import javax.swing.table.AbstractTableModel;
import javax.swing.table.TableColumn; import javax.swing.table.TableColumn;
import org.sleuthkit.autopsy.coreutils.StringExtract.StringExtractUnicodeTable.SCRIPT; import org.sleuthkit.autopsy.coreutils.StringExtract.StringExtractUnicodeTable.SCRIPT;
/** /**
* Simple ingest config panel * Simple ingest config panel
*/ */
public class KeywordSearchIngestSimplePanel extends javax.swing.JPanel { public class KeywordSearchIngestSimplePanel extends javax.swing.JPanel {
private final static Logger logger = Logger.getLogger(KeywordSearchIngestSimplePanel.class.getName()); private final static Logger logger = Logger.getLogger(KeywordSearchIngestSimplePanel.class.getName());
public static final String PROP_OPTIONS = "Keyword Search_Options"; public static final String PROP_OPTIONS = "Keyword Search_Options";
private KeywordTableModel tableModel; private KeywordTableModel tableModel;
private List<KeywordSearchListsAbstract.KeywordSearchList> lists; private List<KeywordSearchListsAbstract.KeywordSearchList> lists;
/** Creates new form KeywordSearchIngestSimplePanel */ /**
* Creates new form KeywordSearchIngestSimplePanel
*/
public KeywordSearchIngestSimplePanel() { public KeywordSearchIngestSimplePanel() {
tableModel = new KeywordTableModel(); tableModel = new KeywordTableModel();
lists = new ArrayList<KeywordSearchListsAbstract.KeywordSearchList>(); lists = new ArrayList<KeywordSearchListsAbstract.KeywordSearchList>();
@ -47,10 +52,10 @@ public class KeywordSearchIngestSimplePanel extends javax.swing.JPanel {
initComponents(); initComponents();
customizeComponents(); customizeComponents();
} }
private void customizeComponents() { private void customizeComponents() {
listsTable.setModel(tableModel); listsTable.setModel(tableModel);
listsTable.setTableHeader(null); listsTable.setTableHeader(null);
listsTable.setSelectionMode(ListSelectionModel.SINGLE_SELECTION); listsTable.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
//customize column witdhs //customize column witdhs
@ -65,13 +70,13 @@ public class KeywordSearchIngestSimplePanel extends javax.swing.JPanel {
column.setPreferredWidth(((int) (width * 0.92))); column.setPreferredWidth(((int) (width * 0.92)));
} }
} }
reloadLangs(); reloadLangs();
reloadEncodings(); reloadEncodings();
} }
public void load() { public void load() {
KeywordSearchListsXML.getCurrent().reload(); KeywordSearchListsXML.getCurrent().reload();
reloadLists(); reloadLists();
reloadLangs(); reloadLangs();
reloadEncodings(); reloadEncodings();
@ -81,8 +86,9 @@ public class KeywordSearchIngestSimplePanel extends javax.swing.JPanel {
public void store() { public void store() {
KeywordSearchListsXML.getCurrent().save(); KeywordSearchListsXML.getCurrent().save();
} }
/** This method is called from within the constructor to /**
* This method is called from within the constructor to
* initialize the form. * initialize the form.
* WARNING: Do NOT modify this code. The content of this method is * WARNING: Do NOT modify this code. The content of this method is
* always regenerated by the Form Editor. * always regenerated by the Form Editor.
@ -106,28 +112,35 @@ public class KeywordSearchIngestSimplePanel extends javax.swing.JPanel {
listsTable.setBackground(new java.awt.Color(240, 240, 240)); listsTable.setBackground(new java.awt.Color(240, 240, 240));
listsTable.setModel(new javax.swing.table.DefaultTableModel( listsTable.setModel(new javax.swing.table.DefaultTableModel(
new Object [][] { new Object[][]{
}, },
new String [] { new String[]{
} }
)); ));
listsTable.setShowHorizontalLines(false); listsTable.setShowHorizontalLines(false);
listsTable.setShowVerticalLines(false); listsTable.setShowVerticalLines(false);
listsScrollPane.setViewportView(listsTable); listsScrollPane.setViewportView(listsTable);
titleLabel.setText(org.openide.util.NbBundle.getMessage(KeywordSearchIngestSimplePanel.class, "KeywordSearchIngestSimplePanel.titleLabel.text")); // NOI18N titleLabel.setText(org.openide.util.NbBundle.getMessage(KeywordSearchIngestSimplePanel.class,
"KeywordSearchIngestSimplePanel.titleLabel.text")); // NOI18N
languagesLabel.setText(org.openide.util.NbBundle.getMessage(KeywordSearchIngestSimplePanel.class, "KeywordSearchIngestSimplePanel.languagesLabel.text")); // NOI18N languagesLabel.setText(org.openide.util.NbBundle.getMessage(KeywordSearchIngestSimplePanel.class,
languagesLabel.setToolTipText(org.openide.util.NbBundle.getMessage(KeywordSearchIngestSimplePanel.class, "KeywordSearchIngestSimplePanel.languagesLabel.toolTipText")); // NOI18N "KeywordSearchIngestSimplePanel.languagesLabel.text")); // NOI18N
languagesLabel.setToolTipText(org.openide.util.NbBundle.getMessage(KeywordSearchIngestSimplePanel.class,
"KeywordSearchIngestSimplePanel.languagesLabel.toolTipText")); // NOI18N
languagesValLabel.setText(org.openide.util.NbBundle.getMessage(KeywordSearchIngestSimplePanel.class, "KeywordSearchIngestSimplePanel.languagesValLabel.text")); // NOI18N languagesValLabel.setText(org.openide.util.NbBundle.getMessage(KeywordSearchIngestSimplePanel.class,
languagesValLabel.setToolTipText(org.openide.util.NbBundle.getMessage(KeywordSearchIngestSimplePanel.class, "KeywordSearchIngestSimplePanel.languagesValLabel.toolTipText")); // NOI18N "KeywordSearchIngestSimplePanel.languagesValLabel.text")); // NOI18N
languagesValLabel.setToolTipText(org.openide.util.NbBundle.getMessage(KeywordSearchIngestSimplePanel.class,
"KeywordSearchIngestSimplePanel.languagesValLabel.toolTipText")); // NOI18N
encodingsLabel.setText(org.openide.util.NbBundle.getMessage(KeywordSearchIngestSimplePanel.class, "KeywordSearchIngestSimplePanel.encodingsLabel.text")); // NOI18N encodingsLabel.setText(org.openide.util.NbBundle.getMessage(KeywordSearchIngestSimplePanel.class,
"KeywordSearchIngestSimplePanel.encodingsLabel.text")); // NOI18N
keywordSearchEncodings.setText(org.openide.util.NbBundle.getMessage(KeywordSearchIngestSimplePanel.class, "KeywordSearchIngestSimplePanel.keywordSearchEncodings.text")); // NOI18N keywordSearchEncodings.setText(org.openide.util.NbBundle.getMessage(KeywordSearchIngestSimplePanel.class,
"KeywordSearchIngestSimplePanel.keywordSearchEncodings.text")); // NOI18N
javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this); javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
this.setLayout(layout); this.setLayout(layout);
@ -187,9 +200,9 @@ public class KeywordSearchIngestSimplePanel extends javax.swing.JPanel {
List<SCRIPT> scripts = KeywordSearchSettings.getStringExtractScripts(); List<SCRIPT> scripts = KeywordSearchSettings.getStringExtractScripts();
StringBuilder langs = new StringBuilder(); StringBuilder langs = new StringBuilder();
langs.append("<html>"); langs.append("<html>");
for(int i=0; i<scripts.size(); i++) { for (int i = 0; i < scripts.size(); i++) {
langs.append(scripts.get(i).toString()); langs.append(scripts.get(i).toString());
if(i+1 < scripts.size()) { if (i + 1 < scripts.size()) {
langs.append(", "); langs.append(", ");
} }
} }
@ -198,22 +211,24 @@ public class KeywordSearchIngestSimplePanel extends javax.swing.JPanel {
this.languagesValLabel.setText(langsS); this.languagesValLabel.setText(langsS);
this.languagesValLabel.setToolTipText(langsS); this.languagesValLabel.setToolTipText(langsS);
} }
private void reloadEncodings() { private void reloadEncodings() {
String utf8 = KeywordSearchSettings.getStringExtractOption(AbstractFileExtract.ExtractOptions.EXTRACT_UTF8.toString()); String utf8 = KeywordSearchSettings
String utf16 = KeywordSearchSettings.getStringExtractOption(AbstractFileExtract.ExtractOptions.EXTRACT_UTF16.toString()); .getStringExtractOption(AbstractFileExtract.ExtractOptions.EXTRACT_UTF8.toString());
String utf16 = KeywordSearchSettings
.getStringExtractOption(AbstractFileExtract.ExtractOptions.EXTRACT_UTF16.toString());
ArrayList<String> encodingsList = new ArrayList<String>(); ArrayList<String> encodingsList = new ArrayList<String>();
if(utf8==null || Boolean.parseBoolean(utf8)) { if (utf8 == null || Boolean.parseBoolean(utf8)) {
encodingsList.add("UTF8"); encodingsList.add("UTF8");
} }
if(utf16==null || Boolean.parseBoolean(utf16)) { if (utf16 == null || Boolean.parseBoolean(utf16)) {
encodingsList.add("UTF16"); encodingsList.add("UTF16");
} }
String encodings = encodingsList.toString(); String encodings = encodingsList.toString();
encodings = encodings.substring(1, encodings.length()-1); encodings = encodings.substring(1, encodings.length() - 1);
keywordSearchEncodings.setText(encodings); keywordSearchEncodings.setText(encodings);
} }
private void reloadLists() { private void reloadLists() {
lists.clear(); lists.clear();
lists.addAll(KeywordSearchListsXML.getCurrent().getListsL()); lists.addAll(KeywordSearchListsXML.getCurrent().getListsL());
@ -234,13 +249,13 @@ public class KeywordSearchIngestSimplePanel extends javax.swing.JPanel {
@Override @Override
public Object getValueAt(int rowIndex, int columnIndex) { public Object getValueAt(int rowIndex, int columnIndex) {
KeywordSearchListsAbstract.KeywordSearchList list = KeywordSearchIngestSimplePanel.this.lists.get(rowIndex); KeywordSearchListsAbstract.KeywordSearchList list = KeywordSearchIngestSimplePanel.this.lists.get(rowIndex);
if(columnIndex == 0) { if (columnIndex == 0) {
return list.getUseForIngest(); return list.getUseForIngest();
} else { } else {
return list.getName(); return list.getName();
} }
} }
@Override @Override
public boolean isCellEditable(int rowIndex, int columnIndex) { public boolean isCellEditable(int rowIndex, int columnIndex) {
return columnIndex == 0; return columnIndex == 0;
@ -248,19 +263,19 @@ public class KeywordSearchIngestSimplePanel extends javax.swing.JPanel {
@Override @Override
public void setValueAt(Object aValue, int rowIndex, int columnIndex) { public void setValueAt(Object aValue, int rowIndex, int columnIndex) {
KeywordSearchListsAbstract.KeywordSearchList list = KeywordSearchIngestSimplePanel.this.lists.get(rowIndex); KeywordSearchListsAbstract.KeywordSearchList list = KeywordSearchIngestSimplePanel.this.lists.get(rowIndex);
if(columnIndex == 0){ if (columnIndex == 0) {
KeywordSearchListsXML loader = KeywordSearchListsXML.getCurrent(); KeywordSearchListsXML loader = KeywordSearchListsXML.getCurrent();
loader.addList(list.getName(), list.getKeywords(), (Boolean) aValue, false); loader.addList(list.getName(), list.getKeywords(), (Boolean) aValue, false);
reloadLists(); reloadLists();
} }
} }
@Override @Override
public Class<?> getColumnClass(int c) { public Class<?> getColumnClass(int c) {
return getValueAt(0, c).getClass(); return getValueAt(0, c).getClass();
} }
} }
} }

View File

@ -26,6 +26,7 @@ import java.util.Date;
import java.util.LinkedHashMap; import java.util.LinkedHashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import org.sleuthkit.autopsy.coreutils.Logger; import org.sleuthkit.autopsy.coreutils.Logger;
import org.sleuthkit.autopsy.coreutils.PlatformUtil; import org.sleuthkit.autopsy.coreutils.PlatformUtil;
import org.sleuthkit.datamodel.BlackboardAttribute; import org.sleuthkit.datamodel.BlackboardAttribute;
@ -53,13 +54,15 @@ public abstract class KeywordSearchListsAbstract {
/** /**
* Property change event support * Property change event support
* In events: For all of these enums, the old value should be null, and * In events: For all of these enums, the old value should be null, and
* the new value should be the keyword list name string. * the new value should be the keyword list name string.
*/ */
public enum ListsEvt { public enum ListsEvt {
LIST_ADDED, LIST_DELETED, LIST_UPDATED LIST_ADDED, LIST_DELETED, LIST_UPDATED
}; }
;
/** /**
* get instance for managing the current keyword list of the application * get instance for managing the current keyword list of the application
@ -77,41 +80,47 @@ public abstract class KeywordSearchListsAbstract {
} }
private void prepopulateLists() { private void prepopulateLists() {
if (! theLists.isEmpty()) { if (!theLists.isEmpty()) {
return; return;
} }
//phone number //phone number
List<Keyword> phones = new ArrayList<Keyword>(); List<Keyword> phones = new ArrayList<Keyword>();
phones.add(new Keyword("[(]{0,1}\\d\\d\\d[)]{0,1}[\\.-]\\d\\d\\d[\\.-]\\d\\d\\d\\d", false, BlackboardAttribute.ATTRIBUTE_TYPE.TSK_PHONE_NUMBER)); phones.add(new Keyword("[(]{0,1}\\d\\d\\d[)]{0,1}[\\.-]\\d\\d\\d[\\.-]\\d\\d\\d\\d", false,
BlackboardAttribute.ATTRIBUTE_TYPE.TSK_PHONE_NUMBER));
//phones.add(new Keyword("\\d{8,10}", false)); //phones.add(new Keyword("\\d{8,10}", false));
//IP address //IP address
List<Keyword> ips = new ArrayList<Keyword>(); List<Keyword> ips = new ArrayList<Keyword>();
ips.add(new Keyword("(([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])", false, BlackboardAttribute.ATTRIBUTE_TYPE.TSK_IP_ADDRESS)); ips.add(new Keyword(
"(([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])",
false, BlackboardAttribute.ATTRIBUTE_TYPE.TSK_IP_ADDRESS));
//email //email
List<Keyword> emails = new ArrayList<Keyword>(); List<Keyword> emails = new ArrayList<Keyword>();
emails.add(new Keyword("[A-Z0-9._%-]+@[A-Z0-9.-]+\\.[A-Z]{2,4}", false, BlackboardAttribute.ATTRIBUTE_TYPE.TSK_EMAIL)); emails.add(new Keyword("[A-Z0-9._%-]+@[A-Z0-9.-]+\\.[A-Z]{2,4}", false,
BlackboardAttribute.ATTRIBUTE_TYPE.TSK_EMAIL));
//URL //URL
List<Keyword> urls = new ArrayList<Keyword>(); List<Keyword> urls = new ArrayList<Keyword>();
//urls.add(new Keyword("http://|https://|^www\\.", false, BlackboardAttribute.ATTRIBUTE_TYPE.TSK_URL)); //urls.add(new Keyword("http://|https://|^www\\.", false, BlackboardAttribute.ATTRIBUTE_TYPE.TSK_URL));
urls.add(new Keyword("((((ht|f)tp(s?))\\://)|www\\.)[a-zA-Z0-9\\-\\.]+\\.([a-zA-Z]{2,5})(\\:[0-9]+)*(/($|[a-zA-Z0-9\\.\\,\\;\\?\\'\\\\+&amp;%\\$#\\=~_\\-]+))*", false, BlackboardAttribute.ATTRIBUTE_TYPE.TSK_URL)); urls.add(new Keyword(
"((((ht|f)tp(s?))\\://)|www\\.)[a-zA-Z0-9\\-\\.]+\\.([a-zA-Z]{2,5})(\\:[0-9]+)*(/($|[a-zA-Z0-9\\.\\,\\;\\?\\'\\\\+&amp;%\\$#\\=~_\\-]+))*",
false, BlackboardAttribute.ATTRIBUTE_TYPE.TSK_URL));
//urls.add(new Keyword("ssh://", false, BlackboardAttribute.ATTRIBUTE_TYPE.TSK_URL)); //urls.add(new Keyword("ssh://", false, BlackboardAttribute.ATTRIBUTE_TYPE.TSK_URL));
//disable messages for harcoded/locked lists //disable messages for harcoded/locked lists
String name; String name;
name = "Phone Numbers"; name = "Phone Numbers";
lockedLists.add(name); lockedLists.add(name);
addList(name, phones, false, false, true); addList(name, phones, false, false, true);
name = "IP Addresses"; name = "IP Addresses";
lockedLists.add(name); lockedLists.add(name);
addList(name, ips, false, false, true); addList(name, ips, false, false, true);
name = "Email Addresses"; name = "Email Addresses";
lockedLists.add(name); lockedLists.add(name);
addList(name, emails, true, false, true); addList(name, emails, true, false, true);
name = "URLs"; name = "URLs";
lockedLists.add(name); lockedLists.add(name);
addList(name, urls, false, false, true); addList(name, urls, false, false, true);
@ -126,7 +135,7 @@ public abstract class KeywordSearchListsAbstract {
//theLists.clear(); //theLists.clear();
//populate only the first time //populate only the first time
prepopulateLists(); prepopulateLists();
//reset all the lists other than locked lists (we don't save them to XML) //reset all the lists other than locked lists (we don't save them to XML)
//we want to preserve state of locked lists //we want to preserve state of locked lists
List<String> toClear = new ArrayList<String>(); List<String> toClear = new ArrayList<String>();
@ -137,8 +146,8 @@ public abstract class KeywordSearchListsAbstract {
} }
for (String clearList : toClear) { for (String clearList : toClear) {
theLists.remove(clearList); theLists.remove(clearList);
} }
if (!this.listFileExists()) { if (!this.listFileExists()) {
//create new if it doesn't exist //create new if it doesn't exist
save(); save();
@ -283,8 +292,8 @@ public abstract class KeywordSearchListsAbstract {
* adds the new word list using name id replacing old one if exists with the * adds the new word list using name id replacing old one if exists with the
* same name * same name
* *
* @param name the name of the new list or list to replace * @param name the name of the new list or list to replace
* @param newList list of keywords * @param newList list of keywords
* @param useForIngest should this list be used for ingest * @param useForIngest should this list be used for ingest
* @return true if old list was replaced * @return true if old list was replaced
*/ */
@ -300,14 +309,15 @@ public abstract class KeywordSearchListsAbstract {
// } // }
changeSupport.firePropertyChange(ListsEvt.LIST_ADDED.toString(), null, name); changeSupport.firePropertyChange(ListsEvt.LIST_ADDED.toString(), null, name);
} else { } else {
theLists.put(name, new KeywordSearchList(name, curList.getDateCreated(), now, useForIngest, ingestMessages, newList, locked)); theLists.put(name, new KeywordSearchList(name, curList.getDateCreated(), now, useForIngest, ingestMessages,
newList, locked));
// if (!locked) { // if (!locked) {
// save(); // save();
// } // }
replaced = true; replaced = true;
changeSupport.firePropertyChange(ListsEvt.LIST_UPDATED.toString(), null, name); changeSupport.firePropertyChange(ListsEvt.LIST_UPDATED.toString(), null, name);
} }
return replaced; return replaced;
} }
@ -323,7 +333,8 @@ public abstract class KeywordSearchListsAbstract {
} }
boolean addList(KeywordSearchList list) { boolean addList(KeywordSearchList list) {
return addList(list.getName(), list.getKeywords(), list.getUseForIngest(), list.getIngestMessages(), list.isLocked()); return addList(list.getName(), list.getKeywords(), list.getUseForIngest(), list.getIngestMessages(),
list.isLocked());
} }
/** /**
@ -380,7 +391,7 @@ public abstract class KeywordSearchListsAbstract {
//boolean saved = save(); //boolean saved = save();
for (KeywordSearchList list : newLists) { for (KeywordSearchList list : newLists) {
changeSupport.firePropertyChange(ListsEvt.LIST_ADDED.toString(), null, list.getName()); changeSupport.firePropertyChange(ListsEvt.LIST_ADDED.toString(), null, list.getName());
} }
for (KeywordSearchList over : overwritten) { for (KeywordSearchList over : overwritten) {
changeSupport.firePropertyChange(ListsEvt.LIST_UPDATED.toString(), null, over.getName()); changeSupport.firePropertyChange(ListsEvt.LIST_UPDATED.toString(), null, over.getName());
@ -403,7 +414,7 @@ public abstract class KeywordSearchListsAbstract {
//deleted = save(); //deleted = save();
} }
changeSupport.firePropertyChange(ListsEvt.LIST_DELETED.toString(), null, name); changeSupport.firePropertyChange(ListsEvt.LIST_DELETED.toString(), null, name);
return true; return true;
} }
@ -412,11 +423,12 @@ public abstract class KeywordSearchListsAbstract {
* writes out current list replacing the last lists file * writes out current list replacing the last lists file
*/ */
public abstract boolean save(); public abstract boolean save();
/** /**
* writes out current list replacing the last lists file * writes out current list replacing the last lists file
*
* @param isExport true is this save operation is an export and not a 'Save * @param isExport true is this save operation is an export and not a 'Save
* As' * As'
*/ */
public abstract boolean save(boolean isExport); public abstract boolean save(boolean isExport);
@ -429,11 +441,11 @@ public abstract class KeywordSearchListsAbstract {
File f = new File(filePath); File f = new File(filePath);
return f.exists() && f.canRead() && f.canWrite(); return f.exists() && f.canRead() && f.canWrite();
} }
public void setUseForIngest(String key, boolean flag) public void setUseForIngest(String key, boolean flag) {
{
theLists.get(key).setUseForIngest(flag); theLists.get(key).setUseForIngest(flag);
} }
/** /**
* a representation of a single keyword list created or loaded * a representation of a single keyword list created or loaded
*/ */
@ -447,7 +459,8 @@ public abstract class KeywordSearchListsAbstract {
private List<Keyword> keywords; private List<Keyword> keywords;
private Boolean locked; private Boolean locked;
KeywordSearchList(String name, Date created, Date modified, Boolean useForIngest, Boolean ingestMessages, List<Keyword> keywords, boolean locked) { KeywordSearchList(String name, Date created, Date modified, Boolean useForIngest, Boolean ingestMessages,
List<Keyword> keywords, boolean locked) {
this.name = name; this.name = name;
this.created = created; this.created = created;
this.modified = modified; this.modified = modified;
@ -457,7 +470,8 @@ public abstract class KeywordSearchListsAbstract {
this.locked = locked; this.locked = locked;
} }
KeywordSearchList(String name, Date created, Date modified, Boolean useForIngest, Boolean ingestMessages, List<Keyword> keywords) { KeywordSearchList(String name, Date created, Date modified, Boolean useForIngest, Boolean ingestMessages,
List<Keyword> keywords) {
this(name, created, modified, useForIngest, ingestMessages, keywords, false); this(name, created, modified, useForIngest, ingestMessages, keywords, false);
} }

View File

@ -30,46 +30,46 @@ import java.util.logging.Level;
/** /**
* @author dfickling * @author dfickling
* KeywordSearchListsEncase adds support for Encase tab-delimited * KeywordSearchListsEncase adds support for Encase tab-delimited
* keyword list exports to Autopsy. * keyword list exports to Autopsy.
* * <p/>
* load() does the I/O operation, converting lines from the text file to * load() does the I/O operation, converting lines from the text file to
* an unsorted list of EncaseFileEntrys * an unsorted list of EncaseFileEntrys
* The next step is to recreate the original folder hierarchy, * The next step is to recreate the original folder hierarchy,
* and finally the EncaseFileEntries are converted to KeywordSearchLists * and finally the EncaseFileEntries are converted to KeywordSearchLists
*
*/ */
class KeywordSearchListsEncase extends KeywordSearchListsAbstract{ class KeywordSearchListsEncase extends KeywordSearchListsAbstract {
ArrayList<EncaseFileEntry> entriesUnsorted; ArrayList<EncaseFileEntry> entriesUnsorted;
EncaseFileEntry rootEntry; EncaseFileEntry rootEntry;
public KeywordSearchListsEncase(String encasePath) { public KeywordSearchListsEncase(String encasePath) {
super(encasePath); super(encasePath);
} }
/** /**
* Follow the EncaseFileEntry hierarchy starting with given entry * Follow the EncaseFileEntry hierarchy starting with given entry
* Create list for each Folder entry, add keyword for each Expression * Create list for each Folder entry, add keyword for each Expression
*
* @param entry * @param entry
* @param parentPath * @param parentPath
*/ */
private void doCreateListsFromEntries(EncaseFileEntry entry, String parentPath) { private void doCreateListsFromEntries(EncaseFileEntry entry, String parentPath) {
String name; String name;
if(parentPath.isEmpty()) { if (parentPath.isEmpty()) {
name = entry.name; name = entry.name;
} else { } else {
name = parentPath + "/" + entry.name; name = parentPath + "/" + entry.name;
} }
List<Keyword> children = new ArrayList<Keyword>(); List<Keyword> children = new ArrayList<Keyword>();
for(EncaseFileEntry child : entry.children) { for (EncaseFileEntry child : entry.children) {
switch(child.type) { switch (child.type) {
case Folder: case Folder:
doCreateListsFromEntries(child, name); doCreateListsFromEntries(child, name);
break; break;
case Expression: case Expression:
if(child.flags.contains(EncaseFlag.pg)) { // Skip GREP keywords if (child.flags.contains(EncaseFlag.pg)) { // Skip GREP keywords
break; break;
} }
children.add(new Keyword(child.value, true)); children.add(new Keyword(child.value, true));
@ -77,22 +77,22 @@ class KeywordSearchListsEncase extends KeywordSearchListsAbstract{
} }
} }
// Give each list a unique name // Give each list a unique name
if(theLists.containsKey(name)) { if (theLists.containsKey(name)) {
int i = 2; int i = 2;
while(theLists.containsKey(name + "(" + i + ")")) { while (theLists.containsKey(name + "(" + i + ")")) {
i+=1; i += 1;
} }
name = name + "(" + i + ")"; name = name + "(" + i + ")";
} }
// Don't create lists if there are no keywords // Don't create lists if there are no keywords
if (!children.isEmpty()) { if (!children.isEmpty()) {
KeywordSearchList newList = new KeywordSearchList(name, new Date(), new Date(), KeywordSearchList newList = new KeywordSearchList(name, new Date(), new Date(),
true, true, children); true, true, children);
theLists.put(name, newList); theLists.put(name, newList);
} }
} }
/** /**
* Convert entriesUnsorted (a list of childless and parentless EncaseFileEntries) into an EncaseFileEntry structure * Convert entriesUnsorted (a list of childless and parentless EncaseFileEntries) into an EncaseFileEntry structure
*/ */
private void doCreateEntryStructure(EncaseFileEntry parent) { private void doCreateEntryStructure(EncaseFileEntry parent) {
@ -101,7 +101,7 @@ class KeywordSearchListsEncase extends KeywordSearchListsAbstract{
child.hasParent = true; child.hasParent = true;
child.parent = parent; child.parent = parent;
parent.addChild(child); parent.addChild(child);
if(!child.isFull()) { if (!child.isFull()) {
doCreateEntryStructure(child); doCreateEntryStructure(child);
} }
if (!parent.isFull()) { if (!parent.isFull()) {
@ -117,7 +117,7 @@ class KeywordSearchListsEncase extends KeywordSearchListsAbstract{
public boolean save() { public boolean save() {
throw new UnsupportedOperationException("Not supported yet."); throw new UnsupportedOperationException("Not supported yet.");
} }
@Override @Override
public boolean save(boolean isExport) { public boolean save(boolean isExport) {
throw new UnsupportedOperationException("Not supported yet."); throw new UnsupportedOperationException("Not supported yet.");
@ -126,11 +126,12 @@ class KeywordSearchListsEncase extends KeywordSearchListsAbstract{
@Override @Override
public boolean load() { public boolean load() {
try { try {
BufferedReader readBuffer = new BufferedReader(new InputStreamReader(new FileInputStream(filePath), "utf-16")); BufferedReader readBuffer = new BufferedReader(
new InputStreamReader(new FileInputStream(filePath), "utf-16"));
String structLine; String structLine;
String metaLine; String metaLine;
entriesUnsorted = new ArrayList<EncaseFileEntry>(); entriesUnsorted = new ArrayList<EncaseFileEntry>();
for(int line = 1; line < 6; line++) { for (int line = 1; line < 6; line++) {
readBuffer.readLine(); readBuffer.readLine();
} }
while ((structLine = readBuffer.readLine()) != null && (metaLine = readBuffer.readLine()) != null) { while ((structLine = readBuffer.readLine()) != null && (metaLine = readBuffer.readLine()) != null) {
@ -141,21 +142,22 @@ class KeywordSearchListsEncase extends KeywordSearchListsAbstract{
String name = metaArr[1]; String name = metaArr[1];
String value = metaArr[2]; String value = metaArr[2];
ArrayList<EncaseFlag> flags = new ArrayList<EncaseFlag>(); ArrayList<EncaseFlag> flags = new ArrayList<EncaseFlag>();
for(int i = 0; i < 17; i++) { for (int i = 0; i < 17; i++) {
if(metaArr.length < i+4) { if (metaArr.length < i + 4) {
continue; continue;
} }
if(!metaArr[i+3].equals("")) { if (!metaArr[i + 3].equals("")) {
flags.add(EncaseFlag.getFlag(i)); flags.add(EncaseFlag.getFlag(i));
} }
} }
entriesUnsorted.add(new EncaseFileEntry(name, value, Integer.parseInt(childCount), false, null, type, flags)); entriesUnsorted
.add(new EncaseFileEntry(name, value, Integer.parseInt(childCount), false, null, type, flags));
} }
this.rootEntry = entriesUnsorted.remove(0); this.rootEntry = entriesUnsorted.remove(0);
doCreateEntryStructure(this.rootEntry); doCreateEntryStructure(this.rootEntry);
doCreateListsFromEntries(this.rootEntry, ""); doCreateListsFromEntries(this.rootEntry, "");
return true; return true;
} catch (FileNotFoundException ex) { } catch (FileNotFoundException ex) {
logger.log(Level.INFO, "File at " + filePath + " does not exist!", ex); logger.log(Level.INFO, "File at " + filePath + " does not exist!", ex);
} catch (IOException ex) { } catch (IOException ex) {
@ -163,21 +165,21 @@ class KeywordSearchListsEncase extends KeywordSearchListsAbstract{
} }
return false; return false;
} }
private enum EncaseMetaType { private enum EncaseMetaType {
Expression, Folder; Expression, Folder;
static EncaseMetaType getType(String type) { static EncaseMetaType getType(String type) {
if(type.equals("5")) { if (type.equals("5")) {
return Folder; return Folder;
} else if(type.equals("")) { } else if (type.equals("")) {
return Expression; return Expression;
} else { } else {
throw new IllegalArgumentException("Unsupported EncaseMetaType: " + type); throw new IllegalArgumentException("Unsupported EncaseMetaType: " + type);
} }
} }
} }
/* /*
* Flags for EncaseFileEntries. * Flags for EncaseFileEntries.
* p8 = UTF-8 * p8 = UTF-8
@ -186,12 +188,12 @@ class KeywordSearchListsEncase extends KeywordSearchListsAbstract{
*/ */
private enum EncaseFlag { private enum EncaseFlag {
pc, pu, pb, p8, p7, pg, an, ph, or, di, um, st, ww, pr, lo, ta, cp; pc, pu, pb, p8, p7, pg, an, ph, or, di, um, st, ww, pr, lo, ta, cp;
static EncaseFlag getFlag(int i) { static EncaseFlag getFlag(int i) {
return EncaseFlag.values()[i]; return EncaseFlag.values()[i];
} }
} }
/** /**
* An entry in the Encase keyword list file. * An entry in the Encase keyword list file.
*/ */
@ -204,7 +206,9 @@ class KeywordSearchListsEncase extends KeywordSearchListsAbstract{
EncaseMetaType type; EncaseMetaType type;
boolean hasParent; boolean hasParent;
ArrayList<EncaseFlag> flags; ArrayList<EncaseFlag> flags;
EncaseFileEntry(String name, String value, int childCount, boolean hasParent, EncaseFileEntry parent, EncaseMetaType type, ArrayList<EncaseFlag> flags) {
EncaseFileEntry(String name, String value, int childCount, boolean hasParent, EncaseFileEntry parent,
EncaseMetaType type, ArrayList<EncaseFlag> flags) {
this.name = name; this.name = name;
this.value = value; this.value = value;
this.childCount = childCount; this.childCount = childCount;
@ -214,12 +218,14 @@ class KeywordSearchListsEncase extends KeywordSearchListsAbstract{
this.type = type; this.type = type;
this.flags = flags; this.flags = flags;
} }
boolean isFull() { boolean isFull() {
return children.size() == childCount; return children.size() == childCount;
} }
void addChild(EncaseFileEntry child) { void addChild(EncaseFileEntry child) {
children.add(child); children.add(child);
} }
} }
} }

View File

@ -31,11 +31,13 @@ import java.util.List;
import org.openide.util.NbBundle; import org.openide.util.NbBundle;
import org.sleuthkit.autopsy.coreutils.Logger; import org.sleuthkit.autopsy.coreutils.Logger;
import javax.swing.JFileChooser; import javax.swing.JFileChooser;
import javax.swing.JOptionPane; import javax.swing.JOptionPane;
import javax.swing.event.ListSelectionListener; import javax.swing.event.ListSelectionListener;
import javax.swing.filechooser.FileNameExtensionFilter; import javax.swing.filechooser.FileNameExtensionFilter;
import javax.swing.table.AbstractTableModel; import javax.swing.table.AbstractTableModel;
import org.sleuthkit.autopsy.corecomponents.OptionsPanel; import org.sleuthkit.autopsy.corecomponents.OptionsPanel;
/** /**
@ -45,14 +47,16 @@ class KeywordSearchListsManagementPanel extends javax.swing.JPanel implements Op
private Logger logger = Logger.getLogger(KeywordSearchListsManagementPanel.class.getName()); private Logger logger = Logger.getLogger(KeywordSearchListsManagementPanel.class.getName());
private KeywordListTableModel tableModel; private KeywordListTableModel tableModel;
/** Creates new form KeywordSearchListImportExportForm */ /**
* Creates new form KeywordSearchListImportExportForm
*/
KeywordSearchListsManagementPanel() { KeywordSearchListsManagementPanel() {
tableModel = new KeywordListTableModel(); tableModel = new KeywordListTableModel();
initComponents(); initComponents();
customizeComponents(); customizeComponents();
} }
private void customizeComponents() { private void customizeComponents() {
@ -92,7 +96,8 @@ class KeywordSearchListsManagementPanel extends javax.swing.JPanel implements Op
} }
/** This method is called from within the constructor to /**
* This method is called from within the constructor to
* initialize the form. * initialize the form.
* WARNING: Do NOT modify this code. The content of this method is * WARNING: Do NOT modify this code. The content of this method is
* always regenerated by the Form Editor. * always regenerated by the Form Editor.
@ -123,76 +128,110 @@ class KeywordSearchListsManagementPanel extends javax.swing.JPanel implements Op
}); });
jScrollPane1.setViewportView(listsTable); jScrollPane1.setViewportView(listsTable);
newListButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/org/sleuthkit/autopsy/keywordsearch/new16.png"))); // NOI18N newListButton.setIcon(new javax.swing.ImageIcon(
newListButton.setText(org.openide.util.NbBundle.getMessage(KeywordSearchListsManagementPanel.class, "KeywordSearchListsManagementPanel.newListButton.text")); // NOI18N getClass().getResource("/org/sleuthkit/autopsy/keywordsearch/new16.png"))); // NOI18N
newListButton.setText(org.openide.util.NbBundle.getMessage(KeywordSearchListsManagementPanel.class,
"KeywordSearchListsManagementPanel.newListButton.text")); // NOI18N
newListButton.addActionListener(new java.awt.event.ActionListener() { newListButton.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) { public void actionPerformed(java.awt.event.ActionEvent evt) {
newListButtonActionPerformed(evt); newListButtonActionPerformed(evt);
} }
}); });
importButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/org/sleuthkit/autopsy/keywordsearch/import16.png"))); // NOI18N importButton.setIcon(new javax.swing.ImageIcon(
importButton.setText(org.openide.util.NbBundle.getMessage(KeywordSearchListsManagementPanel.class, "KeywordSearchListsManagementPanel.importButton.text")); // NOI18N getClass().getResource("/org/sleuthkit/autopsy/keywordsearch/import16.png"))); // NOI18N
importButton.setText(org.openide.util.NbBundle.getMessage(KeywordSearchListsManagementPanel.class,
"KeywordSearchListsManagementPanel.importButton.text")); // NOI18N
importButton.addActionListener(new java.awt.event.ActionListener() { importButton.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) { public void actionPerformed(java.awt.event.ActionEvent evt) {
importButtonActionPerformed(evt); importButtonActionPerformed(evt);
} }
}); });
keywordListsLabel.setText(org.openide.util.NbBundle.getMessage(KeywordSearchListsManagementPanel.class, "KeywordSearchListsManagementPanel.keywordListsLabel.text")); // NOI18N keywordListsLabel.setText(org.openide.util.NbBundle.getMessage(KeywordSearchListsManagementPanel.class,
"KeywordSearchListsManagementPanel.keywordListsLabel.text")); // NOI18N
javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this); javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
this.setLayout(layout); this.setLayout(layout);
layout.setHorizontalGroup( layout.setHorizontalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup() .addGroup(layout.createSequentialGroup()
.addContainerGap() .addContainerGap()
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(jScrollPane1, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) .addComponent(jScrollPane1,
.addGroup(layout.createSequentialGroup() javax.swing.GroupLayout.Alignment.TRAILING,
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) javax.swing.GroupLayout.DEFAULT_SIZE,
.addComponent(keywordListsLabel) javax.swing.GroupLayout.DEFAULT_SIZE,
.addGroup(layout.createSequentialGroup() Short.MAX_VALUE)
.addComponent(newListButton, javax.swing.GroupLayout.PREFERRED_SIZE, 114, javax.swing.GroupLayout.PREFERRED_SIZE) .addGroup(layout.createSequentialGroup()
.addGap(18, 18, 18) .addGroup(layout.createParallelGroup(
.addComponent(importButton, javax.swing.GroupLayout.PREFERRED_SIZE, 126, javax.swing.GroupLayout.PREFERRED_SIZE))) javax.swing.GroupLayout.Alignment.LEADING)
.addGap(0, 4, Short.MAX_VALUE))) .addComponent(keywordListsLabel)
.addContainerGap()) .addGroup(
layout.createSequentialGroup()
.addComponent(
newListButton,
javax.swing.GroupLayout.PREFERRED_SIZE,
114,
javax.swing.GroupLayout.PREFERRED_SIZE)
.addGap(18, 18, 18)
.addComponent(
importButton,
javax.swing.GroupLayout.PREFERRED_SIZE,
126,
javax.swing.GroupLayout.PREFERRED_SIZE)))
.addGap(0, 4, Short.MAX_VALUE)))
.addContainerGap())
); );
layout.setVerticalGroup( layout.setVerticalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup() .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
.addContainerGap() .addContainerGap()
.addComponent(keywordListsLabel) .addComponent(keywordListsLabel)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addPreferredGap(
.addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 414, Short.MAX_VALUE) javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) .addComponent(jScrollPane1,
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) javax.swing.GroupLayout.DEFAULT_SIZE,
.addComponent(newListButton) 414, Short.MAX_VALUE)
.addComponent(importButton)) .addPreferredGap(
.addContainerGap()) javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
.addGroup(layout.createParallelGroup(
javax.swing.GroupLayout.Alignment.BASELINE)
.addComponent(
newListButton)
.addComponent(
importButton))
.addContainerGap())
); );
}// </editor-fold>//GEN-END:initComponents }// </editor-fold>//GEN-END:initComponents
private void newListButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_newListButtonActionPerformed private void newListButtonActionPerformed(
java.awt.event.ActionEvent evt) {//GEN-FIRST:event_newListButtonActionPerformed
KeywordSearchListsXML writer = KeywordSearchListsXML.getCurrent(); KeywordSearchListsXML writer = KeywordSearchListsXML.getCurrent();
String listName = (String) JOptionPane.showInputDialog(null, NbBundle.getMessage(this.getClass(), "KeywordSearch.newKwListTitle"), String listName = (String) JOptionPane
NbBundle.getMessage(this.getClass(), "KeywordSearch.newKeywordListMsg"), JOptionPane.PLAIN_MESSAGE, null, null, ""); .showInputDialog(null, NbBundle.getMessage(this.getClass(), "KeywordSearch.newKwListTitle"),
NbBundle.getMessage(this.getClass(), "KeywordSearch.newKeywordListMsg"),
JOptionPane.PLAIN_MESSAGE, null, null, "");
if (listName == null || listName.trim().equals("")) { if (listName == null || listName.trim().equals("")) {
return; return;
} }
boolean shouldAdd = false; boolean shouldAdd = false;
if (writer.listExists(listName)) { if (writer.listExists(listName)) {
if (writer.getList(listName).isLocked() ) { if (writer.getList(listName).isLocked()) {
boolean replace = KeywordSearchUtil.displayConfirmDialog(NbBundle.getMessage(this.getClass(), "KeywordSearch.newKeywordListMsg"), boolean replace = KeywordSearchUtil
NbBundle.getMessage(this.getClass(), "KeywordSearch.keywordListAlreadyExistMsg", listName), KeywordSearchUtil.DIALOG_MESSAGE_TYPE.WARN); .displayConfirmDialog(NbBundle.getMessage(this.getClass(), "KeywordSearch.newKeywordListMsg"),
NbBundle.getMessage(this.getClass(),
"KeywordSearch.keywordListAlreadyExistMsg", listName),
KeywordSearchUtil.DIALOG_MESSAGE_TYPE.WARN);
if (replace) { if (replace) {
shouldAdd = true; shouldAdd = true;
} }
} } else {
else { boolean replace = KeywordSearchUtil
boolean replace = KeywordSearchUtil.displayConfirmDialog(NbBundle.getMessage(this.getClass(), "KeywordSearch.newKwListTitle"), .displayConfirmDialog(NbBundle.getMessage(this.getClass(), "KeywordSearch.newKwListTitle"),
NbBundle.getMessage(this.getClass(), "KeywordSearch.kwListAlreadyExistMsg", listName), KeywordSearchUtil.DIALOG_MESSAGE_TYPE.WARN); NbBundle.getMessage(this.getClass(),
"KeywordSearch.kwListAlreadyExistMsg", listName),
KeywordSearchUtil.DIALOG_MESSAGE_TYPE.WARN);
if (replace) { if (replace) {
shouldAdd = true; shouldAdd = true;
} }
@ -211,12 +250,14 @@ class KeywordSearchListsManagementPanel extends javax.swing.JPanel implements Op
tableModel.resync(); tableModel.resync();
}//GEN-LAST:event_newListButtonActionPerformed }//GEN-LAST:event_newListButtonActionPerformed
private void importButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_importButtonActionPerformed private void importButtonActionPerformed(
java.awt.event.ActionEvent evt) {//GEN-FIRST:event_importButtonActionPerformed
JFileChooser chooser = new JFileChooser(); JFileChooser chooser = new JFileChooser();
final String[] EXTENSION = new String[]{"xml", "txt"}; final String[] EXTENSION = new String[]{"xml", "txt"};
FileNameExtensionFilter filter = new FileNameExtensionFilter( FileNameExtensionFilter filter = new FileNameExtensionFilter(
NbBundle.getMessage(this.getClass(), "KeywordSearchListsManagementPanel.fileExtensionFilterLbl"), EXTENSION); NbBundle.getMessage(this.getClass(), "KeywordSearchListsManagementPanel.fileExtensionFilterLbl"),
EXTENSION);
chooser.setFileFilter(filter); chooser.setFileFilter(filter);
chooser.setFileSelectionMode(JFileChooser.FILES_ONLY); chooser.setFileSelectionMode(JFileChooser.FILES_ONLY);
@ -229,23 +270,26 @@ class KeywordSearchListsManagementPanel extends javax.swing.JPanel implements Op
//force append extension if not given //force append extension if not given
String fileAbs = selFile.getAbsolutePath(); String fileAbs = selFile.getAbsolutePath();
final KeywordSearchListsAbstract reader; final KeywordSearchListsAbstract reader;
if(KeywordSearchUtil.isXMLList(fileAbs)) { if (KeywordSearchUtil.isXMLList(fileAbs)) {
reader = new KeywordSearchListsXML(fileAbs); reader = new KeywordSearchListsXML(fileAbs);
} else { } else {
reader = new KeywordSearchListsEncase(fileAbs); reader = new KeywordSearchListsEncase(fileAbs);
} }
if (!reader.load()) { if (!reader.load()) {
KeywordSearchUtil.displayDialog( KeywordSearchUtil.displayDialog(
NbBundle.getMessage(this.getClass(), "KeywordSearch.listImportFeatureTitle"), NbBundle.getMessage(this.getClass(), "KeywordSearch.importListFileDialogMsg", fileAbs), KeywordSearchUtil.DIALOG_MESSAGE_TYPE.ERROR); NbBundle.getMessage(this.getClass(), "KeywordSearch.listImportFeatureTitle"),
NbBundle.getMessage(this.getClass(), "KeywordSearch.importListFileDialogMsg", fileAbs),
KeywordSearchUtil.DIALOG_MESSAGE_TYPE.ERROR);
return; return;
} }
List<KeywordSearchListsAbstract.KeywordSearchList> toImport = reader.getListsL(); List<KeywordSearchListsAbstract.KeywordSearchList> toImport = reader.getListsL();
List<KeywordSearchListsAbstract.KeywordSearchList> toImportConfirmed = new ArrayList<KeywordSearchListsAbstract.KeywordSearchList>(); List<KeywordSearchListsAbstract.KeywordSearchList> toImportConfirmed
= new ArrayList<KeywordSearchListsAbstract.KeywordSearchList>();
final KeywordSearchListsXML writer = KeywordSearchListsXML.getCurrent(); final KeywordSearchListsXML writer = KeywordSearchListsXML.getCurrent();
@ -253,16 +297,19 @@ class KeywordSearchListsManagementPanel extends javax.swing.JPanel implements Op
//check name collisions //check name collisions
if (writer.listExists(list.getName())) { if (writer.listExists(list.getName())) {
Object[] options = {NbBundle.getMessage(this.getClass(), "KeywordSearch.yesOwMsg"), Object[] options = {NbBundle.getMessage(this.getClass(), "KeywordSearch.yesOwMsg"),
NbBundle.getMessage(this.getClass(), "KeywordSearch.noSkipMsg"), NbBundle.getMessage(this.getClass(), "KeywordSearch.noSkipMsg"),
NbBundle.getMessage(this.getClass(), "KeywordSearch.cancelImportMsg")}; NbBundle.getMessage(this.getClass(), "KeywordSearch.cancelImportMsg")};
int choice = JOptionPane.showOptionDialog(this, int choice = JOptionPane.showOptionDialog(this,
NbBundle.getMessage(this.getClass(), "KeywordSearch.overwriteListPrompt", list.getName()), NbBundle.getMessage(this.getClass(),
NbBundle.getMessage(this.getClass(), "KeywordSearch.importOwConflict"), "KeywordSearch.overwriteListPrompt",
JOptionPane.YES_NO_CANCEL_OPTION, list.getName()),
JOptionPane.QUESTION_MESSAGE, NbBundle.getMessage(this.getClass(),
null, "KeywordSearch.importOwConflict"),
options, JOptionPane.YES_NO_CANCEL_OPTION,
options[0]); JOptionPane.QUESTION_MESSAGE,
null,
options,
options[0]);
if (choice == JOptionPane.OK_OPTION) { if (choice == JOptionPane.OK_OPTION) {
toImportConfirmed.add(list); toImportConfirmed.add(list);
} else if (choice == JOptionPane.CANCEL_OPTION) { } else if (choice == JOptionPane.CANCEL_OPTION) {
@ -282,7 +329,9 @@ class KeywordSearchListsManagementPanel extends javax.swing.JPanel implements Op
if (!writer.writeLists(toImportConfirmed)) { if (!writer.writeLists(toImportConfirmed)) {
KeywordSearchUtil.displayDialog( KeywordSearchUtil.displayDialog(
NbBundle.getMessage(this.getClass(), "KeywordSearch.listImportFeatureTitle"), NbBundle.getMessage(this.getClass(), "KeywordSearch.kwListFailImportMsg"), KeywordSearchUtil.DIALOG_MESSAGE_TYPE.INFO); NbBundle.getMessage(this.getClass(), "KeywordSearch.listImportFeatureTitle"),
NbBundle.getMessage(this.getClass(), "KeywordSearch.kwListFailImportMsg"),
KeywordSearchUtil.DIALOG_MESSAGE_TYPE.INFO);
} }
} }
@ -290,9 +339,9 @@ class KeywordSearchListsManagementPanel extends javax.swing.JPanel implements Op
}//GEN-LAST:event_importButtonActionPerformed }//GEN-LAST:event_importButtonActionPerformed
private void listsTableKeyPressed(java.awt.event.KeyEvent evt) {//GEN-FIRST:event_listsTableKeyPressed private void listsTableKeyPressed(java.awt.event.KeyEvent evt) {//GEN-FIRST:event_listsTableKeyPressed
if(evt.getKeyCode() == KeyEvent.VK_DELETE) { if (evt.getKeyCode() == KeyEvent.VK_DELETE) {
int[] selected = listsTable.getSelectedRows(); int[] selected = listsTable.getSelectedRows();
if(selected.length == 0) { if (selected.length == 0) {
return; return;
} }
KeywordSearchListsXML deleter = KeywordSearchListsXML.getCurrent(); KeywordSearchListsXML deleter = KeywordSearchListsXML.getCurrent();
@ -319,12 +368,12 @@ class KeywordSearchListsManagementPanel extends javax.swing.JPanel implements Op
public void load() { public void load() {
listsTable.clearSelection(); listsTable.clearSelection();
} }
void resync() { void resync() {
tableModel.resync(); tableModel.resync();
} }
private class KeywordListTableModel extends AbstractTableModel { private class KeywordListTableModel extends AbstractTableModel {
//data //data
@ -368,7 +417,7 @@ class KeywordSearchListsManagementPanel extends javax.swing.JPanel implements Op
//delete selected from handle, events are fired from the handle //delete selected from handle, events are fired from the handle
void deleteSelected(int[] selected) { void deleteSelected(int[] selected) {
List<String> toDel = new ArrayList<String>(); List<String> toDel = new ArrayList<String>();
for(int i = 0; i < selected.length; i++){ for (int i = 0; i < selected.length; i++) {
toDel.add((String) getValueAt(0, selected[i])); toDel.add((String) getValueAt(0, selected[i]));
} }
for (String del : toDel) { for (String del : toDel) {
@ -381,7 +430,7 @@ class KeywordSearchListsManagementPanel extends javax.swing.JPanel implements Op
fireTableDataChanged(); fireTableDataChanged();
} }
} }
void addListSelectionListener(ListSelectionListener l) { void addListSelectionListener(ListSelectionListener l) {
listsTable.getSelectionModel().addListSelectionListener(l); listsTable.getSelectionModel().addListSelectionListener(l);
} }

View File

@ -163,31 +163,38 @@ class KeywordSearchListsViewerPanel extends AbstractKeywordSearchPerformer {
private void initIngest(boolean running) { private void initIngest(boolean running) {
if (running) { if (running) {
ingestRunning = true; ingestRunning = true;
searchAddButton.setText(NbBundle.getMessage(this.getClass(), "KeywordSearchListsViewerPanel.initIngest.addIngestTitle")); searchAddButton.setText(
searchAddButton.setToolTipText(NbBundle.getMessage(this.getClass(), "KeywordSearchListsViewerPanel.initIngest.addIngestMsg" )); NbBundle.getMessage(this.getClass(), "KeywordSearchListsViewerPanel.initIngest.addIngestTitle"));
searchAddButton.setToolTipText(
NbBundle.getMessage(this.getClass(), "KeywordSearchListsViewerPanel.initIngest.addIngestMsg"));
listsTableModel.resync(); listsTableModel.resync();
} else { } else {
ingestRunning = false; ingestRunning = false;
searchAddButton.setText(NbBundle.getMessage(this.getClass(), "KeywordSearchListsViewerPanel.initIngest.searchIngestTitle")); searchAddButton.setText(
searchAddButton.setToolTipText(NbBundle.getMessage(this.getClass(), "KeywordSearchListsViewerPanel.initIngest.addIdxSearchMsg")); NbBundle.getMessage(this.getClass(), "KeywordSearchListsViewerPanel.initIngest.searchIngestTitle"));
searchAddButton.setToolTipText(
NbBundle.getMessage(this.getClass(), "KeywordSearchListsViewerPanel.initIngest.addIdxSearchMsg"));
listsTableModel.resync(); listsTableModel.resync();
} }
updateIngestIndexLabel(running); updateIngestIndexLabel(running);
} }
private void updateIngestIndexLabel(boolean ingestRunning) { private void updateIngestIndexLabel(boolean ingestRunning) {
if (ingestRunning) { if (ingestRunning) {
ingestIndexLabel.setText(NbBundle.getMessage(this.getClass(), "KeywordSearchListsViewerPanel.initIngest.ongoingIngestMsg", filesIndexed)); ingestIndexLabel.setText(
} NbBundle.getMessage(this.getClass(), "KeywordSearchListsViewerPanel.initIngest.ongoingIngestMsg",
else { filesIndexed));
ingestIndexLabel.setText(NbBundle.getMessage(this.getClass(), "KeywordSearchListsViewerPanel.initIngest.fileIndexCtMsg", filesIndexed)); } else {
ingestIndexLabel.setText(
NbBundle.getMessage(this.getClass(), "KeywordSearchListsViewerPanel.initIngest.fileIndexCtMsg",
filesIndexed));
} }
} }
@Override @Override
protected void postFilesIndexedChange() { protected void postFilesIndexedChange() {
updateIngestIndexLabel(ingestRunning); updateIngestIndexLabel(ingestRunning);
} }
/** /**
@ -234,18 +241,22 @@ class KeywordSearchListsViewerPanel extends AbstractKeywordSearchPerformer {
jSplitPane1.setRightComponent(rightPane); jSplitPane1.setRightComponent(rightPane);
manageListsButton.setText(org.openide.util.NbBundle.getMessage(KeywordSearchListsViewerPanel.class, "KeywordSearchListsViewerPanel.manageListsButton.text")); // NOI18N manageListsButton.setText(org.openide.util.NbBundle.getMessage(KeywordSearchListsViewerPanel.class,
manageListsButton.setToolTipText(org.openide.util.NbBundle.getMessage(KeywordSearchListsViewerPanel.class, "KeywordSearchListsViewerPanel.manageListsButton.toolTipText")); // NOI18N "KeywordSearchListsViewerPanel.manageListsButton.text")); // NOI18N
manageListsButton.setToolTipText(org.openide.util.NbBundle.getMessage(KeywordSearchListsViewerPanel.class,
"KeywordSearchListsViewerPanel.manageListsButton.toolTipText")); // NOI18N
manageListsButton.addActionListener(new java.awt.event.ActionListener() { manageListsButton.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) { public void actionPerformed(java.awt.event.ActionEvent evt) {
manageListsButtonActionPerformed(evt); manageListsButtonActionPerformed(evt);
} }
}); });
searchAddButton.setText(org.openide.util.NbBundle.getMessage(KeywordSearchListsViewerPanel.class, "KeywordSearchListsViewerPanel.searchAddButton.text")); // NOI18N searchAddButton.setText(org.openide.util.NbBundle.getMessage(KeywordSearchListsViewerPanel.class,
"KeywordSearchListsViewerPanel.searchAddButton.text")); // NOI18N
ingestIndexLabel.setFont(new java.awt.Font("Tahoma", 0, 10)); // NOI18N ingestIndexLabel.setFont(new java.awt.Font("Tahoma", 0, 10)); // NOI18N
ingestIndexLabel.setText(org.openide.util.NbBundle.getMessage(KeywordSearchListsViewerPanel.class, "KeywordSearchListsViewerPanel.ingestIndexLabel.text")); // NOI18N ingestIndexLabel.setText(org.openide.util.NbBundle.getMessage(KeywordSearchListsViewerPanel.class,
"KeywordSearchListsViewerPanel.ingestIndexLabel.text")); // NOI18N
javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this); javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
this.setLayout(layout); this.setLayout(layout);
@ -278,9 +289,11 @@ class KeywordSearchListsViewerPanel extends AbstractKeywordSearchPerformer {
); );
}// </editor-fold>//GEN-END:initComponents }// </editor-fold>//GEN-END:initComponents
private void manageListsButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_manageListsButtonActionPerformed private void manageListsButtonActionPerformed(
java.awt.event.ActionEvent evt) {//GEN-FIRST:event_manageListsButtonActionPerformed
SystemAction.get(KeywordSearchConfigurationAction.class).performAction(); SystemAction.get(KeywordSearchConfigurationAction.class).performAction();
}//GEN-LAST:event_manageListsButtonActionPerformed }//GEN-LAST:event_manageListsButtonActionPerformed
// Variables declaration - do not modify//GEN-BEGIN:variables // Variables declaration - do not modify//GEN-BEGIN:variables
private javax.swing.JLabel ingestIndexLabel; private javax.swing.JLabel ingestIndexLabel;
private javax.swing.JSplitPane jSplitPane1; private javax.swing.JSplitPane jSplitPane1;
@ -440,7 +453,8 @@ class KeywordSearchListsViewerPanel extends AbstractKeywordSearchPerformer {
} }
List<KeywordSearchListsAbstract.KeywordSearchList> getSelectedListsL() { List<KeywordSearchListsAbstract.KeywordSearchList> getSelectedListsL() {
List<KeywordSearchListsAbstract.KeywordSearchList> ret = new ArrayList<KeywordSearchListsAbstract.KeywordSearchList>(); List<KeywordSearchListsAbstract.KeywordSearchList> ret
= new ArrayList<KeywordSearchListsAbstract.KeywordSearchList>();
for (String s : getSelectedLists()) { for (String s : getSelectedLists()) {
ret.add(listsHandle.getList(s)); ret.add(listsHandle.getList(s));
} }

View File

@ -28,6 +28,7 @@ import java.util.logging.Level;
import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException; import javax.xml.parsers.ParserConfigurationException;
import org.sleuthkit.autopsy.coreutils.Logger; import org.sleuthkit.autopsy.coreutils.Logger;
import org.sleuthkit.autopsy.coreutils.XMLUtil; import org.sleuthkit.autopsy.coreutils.XMLUtil;
import org.sleuthkit.datamodel.BlackboardAttribute; import org.sleuthkit.datamodel.BlackboardAttribute;
@ -39,7 +40,7 @@ import org.w3c.dom.NodeList;
* Manages reading and writing of keyword lists to user settings XML file keywords.xml * Manages reading and writing of keyword lists to user settings XML file keywords.xml
* or to any file provided in constructor * or to any file provided in constructor
*/ */
public class KeywordSearchListsXML extends KeywordSearchListsAbstract{ public class KeywordSearchListsXML extends KeywordSearchListsAbstract {
private static final String ROOT_EL = "keyword_lists"; private static final String ROOT_EL = "keyword_lists";
private static final String LIST_EL = "keyword_list"; private static final String LIST_EL = "keyword_list";
@ -57,23 +58,23 @@ public class KeywordSearchListsXML extends KeywordSearchListsAbstract{
private static final Logger logger = Logger.getLogger(KeywordSearchListsXML.class.getName()); private static final Logger logger = Logger.getLogger(KeywordSearchListsXML.class.getName());
private DateFormat dateFormatter; private DateFormat dateFormatter;
/** /**
* Constructor to obtain handle on other that the current keyword list * Constructor to obtain handle on other that the current keyword list
* (such as for import or export) * (such as for import or export)
*
* @param xmlFile xmlFile to obtain KeywordSearchListsXML handle on * @param xmlFile xmlFile to obtain KeywordSearchListsXML handle on
*/ */
KeywordSearchListsXML(String xmlFile) { KeywordSearchListsXML(String xmlFile) {
super(xmlFile); super(xmlFile);
dateFormatter = new SimpleDateFormat(DATE_FORMAT); dateFormatter = new SimpleDateFormat(DATE_FORMAT);
} }
@Override @Override
public boolean save() { public boolean save() {
return save(false); return save(false);
} }
@Override @Override
public boolean save(boolean isExport) { public boolean save(boolean isExport) {
boolean success = false; boolean success = false;
@ -102,7 +103,7 @@ public class KeywordSearchListsXML extends KeywordSearchListsAbstract{
listEl.setAttribute(LIST_NAME_ATTR, listName); listEl.setAttribute(LIST_NAME_ATTR, listName);
listEl.setAttribute(LIST_CREATE_ATTR, created); listEl.setAttribute(LIST_CREATE_ATTR, created);
listEl.setAttribute(LIST_MOD_ATTR, modified); listEl.setAttribute(LIST_MOD_ATTR, modified);
// only write the 'useForIngest' and 'ingestMessages' attributes // only write the 'useForIngest' and 'ingestMessages' attributes
// if we're not exporting the list // if we're not exporting the list
if (!isExport) { if (!isExport) {
@ -112,7 +113,7 @@ public class KeywordSearchListsXML extends KeywordSearchListsAbstract{
for (Keyword keyword : keywords) { for (Keyword keyword : keywords) {
Element keywordEl = doc.createElement(KEYWORD_EL); Element keywordEl = doc.createElement(KEYWORD_EL);
String literal = keyword.isLiteral()?"true":"false"; String literal = keyword.isLiteral() ? "true" : "false";
keywordEl.setAttribute(KEYWORD_LITERAL_ATTR, literal); keywordEl.setAttribute(KEYWORD_LITERAL_ATTR, literal);
BlackboardAttribute.ATTRIBUTE_TYPE selectorType = keyword.getType(); BlackboardAttribute.ATTRIBUTE_TYPE selectorType = keyword.getType();
if (selectorType != null) { if (selectorType != null) {
@ -154,30 +155,29 @@ public class KeywordSearchListsXML extends KeywordSearchListsAbstract{
final String name = listEl.getAttribute(LIST_NAME_ATTR); final String name = listEl.getAttribute(LIST_NAME_ATTR);
final String created = listEl.getAttribute(LIST_CREATE_ATTR); final String created = listEl.getAttribute(LIST_CREATE_ATTR);
final String modified = listEl.getAttribute(LIST_MOD_ATTR); final String modified = listEl.getAttribute(LIST_MOD_ATTR);
//set these bools to true by default, if they don't exist in XML //set these bools to true by default, if they don't exist in XML
Boolean useForIngestBool; Boolean useForIngestBool;
Boolean ingestMessagesBool; Boolean ingestMessagesBool;
if (listEl.hasAttribute(LIST_USE_FOR_INGEST) ) { if (listEl.hasAttribute(LIST_USE_FOR_INGEST)) {
useForIngestBool = Boolean.parseBoolean(listEl.getAttribute(LIST_USE_FOR_INGEST)); useForIngestBool = Boolean.parseBoolean(listEl.getAttribute(LIST_USE_FOR_INGEST));
} } else {
else {
useForIngestBool = true; useForIngestBool = true;
} }
if (listEl.hasAttribute(LIST_INGEST_MSGS)) { if (listEl.hasAttribute(LIST_INGEST_MSGS)) {
ingestMessagesBool = Boolean.parseBoolean(listEl.getAttribute(LIST_INGEST_MSGS)); ingestMessagesBool = Boolean.parseBoolean(listEl.getAttribute(LIST_INGEST_MSGS));
} } else {
else {
ingestMessagesBool = true; ingestMessagesBool = true;
} }
Date createdDate = dateFormatter.parse(created); Date createdDate = dateFormatter.parse(created);
Date modDate = dateFormatter.parse(modified); Date modDate = dateFormatter.parse(modified);
List<Keyword> words = new ArrayList<Keyword>(); List<Keyword> words = new ArrayList<Keyword>();
KeywordSearchList list = new KeywordSearchList(name, createdDate, modDate, useForIngestBool, ingestMessagesBool, words); KeywordSearchList list = new KeywordSearchList(name, createdDate, modDate, useForIngestBool,
ingestMessagesBool, words);
//parse all words //parse all words
NodeList wordsNList = listEl.getElementsByTagName(KEYWORD_EL); NodeList wordsNList = listEl.getElementsByTagName(KEYWORD_EL);
@ -188,12 +188,13 @@ public class KeywordSearchListsXML extends KeywordSearchListsAbstract{
boolean isLiteral = literal.equals("true"); boolean isLiteral = literal.equals("true");
Keyword keyword = new Keyword(wordEl.getTextContent(), isLiteral); Keyword keyword = new Keyword(wordEl.getTextContent(), isLiteral);
String selector = wordEl.getAttribute(KEYWORD_SELECTOR_ATTR); String selector = wordEl.getAttribute(KEYWORD_SELECTOR_ATTR);
if (! selector.equals("")) { if (!selector.equals("")) {
BlackboardAttribute.ATTRIBUTE_TYPE selectorType = BlackboardAttribute.ATTRIBUTE_TYPE.fromLabel(selector); BlackboardAttribute.ATTRIBUTE_TYPE selectorType = BlackboardAttribute.ATTRIBUTE_TYPE
.fromLabel(selector);
keyword.setType(selectorType); keyword.setType(selectorType);
} }
words.add(keyword); words.add(keyword);
} }
theLists.put(name, list); theLists.put(name, list);
} }

View File

@ -35,6 +35,6 @@ class KeywordSearchModuleException extends Exception {
public KeywordSearchModuleException(Throwable cause) { public KeywordSearchModuleException(Throwable cause) {
super(cause); super(cause);
} }
} }

View File

@ -7,17 +7,19 @@ package org.sleuthkit.autopsy.keywordsearch;
import java.beans.PropertyChangeListener; import java.beans.PropertyChangeListener;
import java.beans.PropertyChangeSupport; import java.beans.PropertyChangeSupport;
import javax.swing.JComponent; import javax.swing.JComponent;
import org.netbeans.spi.options.OptionsPanelController; import org.netbeans.spi.options.OptionsPanelController;
import org.openide.util.HelpCtx; import org.openide.util.HelpCtx;
import org.openide.util.Lookup; import org.openide.util.Lookup;
@OptionsPanelController.TopLevelRegistration( @OptionsPanelController.TopLevelRegistration(
categoryName = "#OptionsCategory_Name_KeywordSearchOptions", categoryName = "#OptionsCategory_Name_KeywordSearchOptions",
iconBase = "org/sleuthkit/autopsy/keywordsearch/options-icon.png", iconBase = "org/sleuthkit/autopsy/keywordsearch/options-icon.png",
position = 2, position = 2,
keywords = "#OptionsCategory_Keywords_KeywordSearchOptions", keywords = "#OptionsCategory_Keywords_KeywordSearchOptions",
keywordsCategory = "KeywordSearchOptions") keywordsCategory = "KeywordSearchOptions")
@org.openide.util.NbBundle.Messages({"OptionsCategory_Name_KeywordSearchOptions=Keyword Search", "OptionsCategory_Keywords_KeywordSearchOptions=Keyword Search"}) @org.openide.util.NbBundle.Messages({"OptionsCategory_Name_KeywordSearchOptions=Keyword Search",
"OptionsCategory_Keywords_KeywordSearchOptions=Keyword Search"})
public final class KeywordSearchOptionsPanelController extends OptionsPanelController { public final class KeywordSearchOptionsPanelController extends OptionsPanelController {
private KeywordSearchConfigurationPanel panel; private KeywordSearchConfigurationPanel panel;

View File

@ -34,20 +34,23 @@ import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener; import java.beans.PropertyChangeListener;
import java.util.List; import java.util.List;
import java.util.logging.Level; import java.util.logging.Level;
import org.sleuthkit.autopsy.coreutils.Logger; import org.sleuthkit.autopsy.coreutils.Logger;
import javax.swing.JMenuItem; import javax.swing.JMenuItem;
import javax.swing.SwingUtilities; import javax.swing.SwingUtilities;
import javax.swing.event.PopupMenuEvent; import javax.swing.event.PopupMenuEvent;
import javax.swing.event.PopupMenuListener; import javax.swing.event.PopupMenuListener;
import org.apache.solr.client.solrj.SolrServerException; import org.apache.solr.client.solrj.SolrServerException;
import org.sleuthkit.autopsy.casemodule.Case; import org.sleuthkit.autopsy.casemodule.Case;
/** /**
* Keyword search toolbar (in upper right, by default) which allows to search for single terms or phrases * Keyword search toolbar (in upper right, by default) which allows to search for single terms or phrases
* * <p/>
* The toolbar uses a different font from the rest of the application, Monospaced 14, * The toolbar uses a different font from the rest of the application, Monospaced 14,
* due to the necessity to find a font that displays both Arabic and Asian fonts at an acceptable size. * due to the necessity to find a font that displays both Arabic and Asian fonts at an acceptable size.
* The default, Tahoma 14, could not perform this task at the desired size, and neither could numerous other fonts. * The default, Tahoma 14, could not perform this task at the desired size, and neither could numerous other fonts.
*/ */
class KeywordSearchPanel extends AbstractKeywordSearchPerformer { class KeywordSearchPanel extends AbstractKeywordSearchPerformer {
@ -57,7 +60,9 @@ class KeywordSearchPanel extends AbstractKeywordSearchPerformer {
private boolean entered = false; private boolean entered = false;
private static KeywordSearchPanel instance; private static KeywordSearchPanel instance;
/** Creates new form KeywordSearchPanel */ /**
* Creates new form KeywordSearchPanel
*/
private KeywordSearchPanel() { private KeywordSearchPanel() {
initComponents(); initComponents();
customizeComponents(); customizeComponents();
@ -78,8 +83,7 @@ class KeywordSearchPanel extends AbstractKeywordSearchPerformer {
//nothing to update //nothing to update
} }
private void customizeComponents() { private void customizeComponents() {
listener = new KeywordPropertyChangeListener(); listener = new KeywordPropertyChangeListener();
@ -172,7 +176,8 @@ class KeywordSearchPanel extends AbstractKeywordSearchPerformer {
entered = false; entered = false;
} }
/** This method is called from within the constructor to /**
* This method is called from within the constructor to
* initialize the form. * initialize the form.
* WARNING: Do NOT modify this code. The content of this method is * WARNING: Do NOT modify this code. The content of this method is
* always regenerated by the Form Editor. * always regenerated by the Form Editor.
@ -195,19 +200,24 @@ class KeywordSearchPanel extends AbstractKeywordSearchPerformer {
searchButton = new javax.swing.JLabel(); searchButton = new javax.swing.JLabel();
listsButton = new javax.swing.JButton(); listsButton = new javax.swing.JButton();
regExCheckboxMenuItem.setText(org.openide.util.NbBundle.getMessage(KeywordSearchPanel.class, "KeywordSearchPanel.regExCheckboxMenuItem.text")); // NOI18N regExCheckboxMenuItem.setText(org.openide.util.NbBundle.getMessage(KeywordSearchPanel.class,
"KeywordSearchPanel.regExCheckboxMenuItem.text")); // NOI18N
settingsMenu.add(regExCheckboxMenuItem); settingsMenu.add(regExCheckboxMenuItem);
cutMenuItem.setText(org.openide.util.NbBundle.getMessage(KeywordSearchPanel.class, "KeywordSearchPanel.cutMenuItem.text")); // NOI18N cutMenuItem.setText(org.openide.util.NbBundle.getMessage(KeywordSearchPanel.class,
"KeywordSearchPanel.cutMenuItem.text")); // NOI18N
rightClickMenu.add(cutMenuItem); rightClickMenu.add(cutMenuItem);
copyMenuItem.setText(org.openide.util.NbBundle.getMessage(KeywordSearchPanel.class, "KeywordSearchPanel.copyMenuItem.text")); // NOI18N copyMenuItem.setText(org.openide.util.NbBundle.getMessage(KeywordSearchPanel.class,
"KeywordSearchPanel.copyMenuItem.text")); // NOI18N
rightClickMenu.add(copyMenuItem); rightClickMenu.add(copyMenuItem);
pasteMenuItem.setText(org.openide.util.NbBundle.getMessage(KeywordSearchPanel.class, "KeywordSearchPanel.pasteMenuItem.text")); // NOI18N pasteMenuItem.setText(org.openide.util.NbBundle.getMessage(KeywordSearchPanel.class,
"KeywordSearchPanel.pasteMenuItem.text")); // NOI18N
rightClickMenu.add(pasteMenuItem); rightClickMenu.add(pasteMenuItem);
selectAllMenuItem.setText(org.openide.util.NbBundle.getMessage(KeywordSearchPanel.class, "KeywordSearchPanel.selectAllMenuItem.text")); // NOI18N selectAllMenuItem.setText(org.openide.util.NbBundle.getMessage(KeywordSearchPanel.class,
"KeywordSearchPanel.selectAllMenuItem.text")); // NOI18N
rightClickMenu.add(selectAllMenuItem); rightClickMenu.add(selectAllMenuItem);
setOpaque(false); setOpaque(false);
@ -217,7 +227,8 @@ class KeywordSearchPanel extends AbstractKeywordSearchPerformer {
searchBox.setFont(new java.awt.Font("Monospaced", 0, 14)); // NOI18N searchBox.setFont(new java.awt.Font("Monospaced", 0, 14)); // NOI18N
searchBox.setForeground(java.awt.Color.lightGray); searchBox.setForeground(java.awt.Color.lightGray);
searchBox.setText(org.openide.util.NbBundle.getMessage(KeywordSearchPanel.class, "KeywordSearchPanel.searchBox.text")); // NOI18N searchBox.setText(org.openide.util.NbBundle.getMessage(KeywordSearchPanel.class,
"KeywordSearchPanel.searchBox.text")); // NOI18N
searchBox.setBorder(javax.swing.BorderFactory.createEmptyBorder(1, 3, 4, 1)); searchBox.setBorder(javax.swing.BorderFactory.createEmptyBorder(1, 3, 4, 1));
searchBox.setEnabled(false); searchBox.setEnabled(false);
searchBox.addActionListener(new java.awt.event.ActionListener() { searchBox.addActionListener(new java.awt.event.ActionListener() {
@ -226,8 +237,10 @@ class KeywordSearchPanel extends AbstractKeywordSearchPerformer {
} }
}); });
settingsLabel.setIcon(new javax.swing.ImageIcon(getClass().getResource("/org/sleuthkit/autopsy/keywordsearch/dropdown-icon.png"))); // NOI18N settingsLabel.setIcon(new javax.swing.ImageIcon(
settingsLabel.setText(org.openide.util.NbBundle.getMessage(KeywordSearchPanel.class, "KeywordSearchPanel.settingsLabel.text")); // NOI18N getClass().getResource("/org/sleuthkit/autopsy/keywordsearch/dropdown-icon.png"))); // NOI18N
settingsLabel.setText(org.openide.util.NbBundle.getMessage(KeywordSearchPanel.class,
"KeywordSearchPanel.settingsLabel.text")); // NOI18N
settingsLabel.setBorder(javax.swing.BorderFactory.createEmptyBorder(1, 2, 1, 2)); settingsLabel.setBorder(javax.swing.BorderFactory.createEmptyBorder(1, 2, 1, 2));
settingsLabel.setEnabled(false); settingsLabel.setEnabled(false);
settingsLabel.setMaximumSize(new java.awt.Dimension(23, 20)); settingsLabel.setMaximumSize(new java.awt.Dimension(23, 20));
@ -237,16 +250,20 @@ class KeywordSearchPanel extends AbstractKeywordSearchPerformer {
public void mouseEntered(java.awt.event.MouseEvent evt) { public void mouseEntered(java.awt.event.MouseEvent evt) {
settingsLabelMouseEntered(evt); settingsLabelMouseEntered(evt);
} }
public void mouseExited(java.awt.event.MouseEvent evt) { public void mouseExited(java.awt.event.MouseEvent evt) {
settingsLabelMouseExited(evt); settingsLabelMouseExited(evt);
} }
public void mousePressed(java.awt.event.MouseEvent evt) { public void mousePressed(java.awt.event.MouseEvent evt) {
settingsLabelMousePressed(evt); settingsLabelMousePressed(evt);
} }
}); });
searchButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/org/sleuthkit/autopsy/keywordsearch/search-icon.png"))); // NOI18N searchButton.setIcon(new javax.swing.ImageIcon(
searchButton.setText(org.openide.util.NbBundle.getMessage(KeywordSearchPanel.class, "KeywordSearchPanel.searchButton.text")); // NOI18N getClass().getResource("/org/sleuthkit/autopsy/keywordsearch/search-icon.png"))); // NOI18N
searchButton.setText(org.openide.util.NbBundle.getMessage(KeywordSearchPanel.class,
"KeywordSearchPanel.searchButton.text")); // NOI18N
searchButton.setBorder(javax.swing.BorderFactory.createEmptyBorder(1, 2, 1, 2)); searchButton.setBorder(javax.swing.BorderFactory.createEmptyBorder(1, 2, 1, 2));
searchButton.setEnabled(false); searchButton.setEnabled(false);
searchButton.setMaximumSize(new java.awt.Dimension(23, 20)); searchButton.setMaximumSize(new java.awt.Dimension(23, 20));
@ -276,13 +293,16 @@ class KeywordSearchPanel extends AbstractKeywordSearchPerformer {
.addComponent(searchButton, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) .addComponent(searchButton, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
); );
listsButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/org/sleuthkit/autopsy/keywordsearch/watchbutton-icon.png"))); // NOI18N listsButton.setIcon(new javax.swing.ImageIcon(
getClass().getResource("/org/sleuthkit/autopsy/keywordsearch/watchbutton-icon.png"))); // NOI18N
listsButton.setText(org.openide.util.NbBundle.getMessage(KeywordSearchPanel.class, "ListBundleName")); // NOI18N listsButton.setText(org.openide.util.NbBundle.getMessage(KeywordSearchPanel.class, "ListBundleName")); // NOI18N
listsButton.setBorderPainted(false); listsButton.setBorderPainted(false);
listsButton.setContentAreaFilled(false); listsButton.setContentAreaFilled(false);
listsButton.setEnabled(false); listsButton.setEnabled(false);
listsButton.setRolloverIcon(new javax.swing.ImageIcon(getClass().getResource("/org/sleuthkit/autopsy/keywordsearch/watchbutton-icon-rollover.png"))); // NOI18N listsButton.setRolloverIcon(new javax.swing.ImageIcon(getClass().getResource(
listsButton.setRolloverSelectedIcon(new javax.swing.ImageIcon(getClass().getResource("/org/sleuthkit/autopsy/keywordsearch/watchbutton-icon-pressed.png"))); // NOI18N "/org/sleuthkit/autopsy/keywordsearch/watchbutton-icon-rollover.png"))); // NOI18N
listsButton.setRolloverSelectedIcon(new javax.swing.ImageIcon(
getClass().getResource("/org/sleuthkit/autopsy/keywordsearch/watchbutton-icon-pressed.png"))); // NOI18N
listsButton.addMouseListener(new java.awt.event.MouseAdapter() { listsButton.addMouseListener(new java.awt.event.MouseAdapter() {
public void mousePressed(java.awt.event.MouseEvent evt) { public void mousePressed(java.awt.event.MouseEvent evt) {
listsButtonMousePressed(evt); listsButtonMousePressed(evt);
@ -297,17 +317,21 @@ class KeywordSearchPanel extends AbstractKeywordSearchPerformer {
javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this); javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
this.setLayout(layout); this.setLayout(layout);
layout.setHorizontalGroup( layout.setHorizontalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup() .addGroup(layout.createSequentialGroup()
.addComponent(listsButton) .addComponent(listsButton)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, 18, Short.MAX_VALUE) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, 18,
.addComponent(searchBoxPanel, javax.swing.GroupLayout.PREFERRED_SIZE, 244, javax.swing.GroupLayout.PREFERRED_SIZE) Short.MAX_VALUE)
.addContainerGap()) .addComponent(searchBoxPanel, javax.swing.GroupLayout.PREFERRED_SIZE, 244,
javax.swing.GroupLayout.PREFERRED_SIZE)
.addContainerGap())
); );
layout.setVerticalGroup( layout.setVerticalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(listsButton, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) .addComponent(listsButton, javax.swing.GroupLayout.Alignment.TRAILING,
.addComponent(searchBoxPanel, javax.swing.GroupLayout.DEFAULT_SIZE, 27, Short.MAX_VALUE) javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE,
Short.MAX_VALUE)
.addComponent(searchBoxPanel, javax.swing.GroupLayout.DEFAULT_SIZE, 27, Short.MAX_VALUE)
); );
}// </editor-fold>//GEN-END:initComponents }// </editor-fold>//GEN-END:initComponents
@ -331,7 +355,8 @@ class KeywordSearchPanel extends AbstractKeywordSearchPerformer {
maybeShowListsPopup(evt); maybeShowListsPopup(evt);
}//GEN-LAST:event_listsButtonMousePressed }//GEN-LAST:event_listsButtonMousePressed
private void listsButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_listsButtonActionPerformed private void listsButtonActionPerformed(
java.awt.event.ActionEvent evt) {//GEN-FIRST:event_listsButtonActionPerformed
// TODO add your handling code here: // TODO add your handling code here:
}//GEN-LAST:event_listsButtonActionPerformed }//GEN-LAST:event_listsButtonActionPerformed
@ -340,12 +365,15 @@ class KeywordSearchPanel extends AbstractKeywordSearchPerformer {
}//GEN-LAST:event_searchButtonMousePressed }//GEN-LAST:event_searchButtonMousePressed
private void settingsLabelMouseEntered(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_settingsLabelMouseEntered private void settingsLabelMouseEntered(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_settingsLabelMouseEntered
settingsLabel.setIcon(new javax.swing.ImageIcon(getClass().getResource("/org/sleuthkit/autopsy/keywordsearch/dropdown-icon-rollover.png"))); settingsLabel.setIcon(new javax.swing.ImageIcon(
getClass().getResource("/org/sleuthkit/autopsy/keywordsearch/dropdown-icon-rollover.png")));
}//GEN-LAST:event_settingsLabelMouseEntered }//GEN-LAST:event_settingsLabelMouseEntered
private void settingsLabelMouseExited(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_settingsLabelMouseExited private void settingsLabelMouseExited(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_settingsLabelMouseExited
settingsLabel.setIcon(new javax.swing.ImageIcon(getClass().getResource("/org/sleuthkit/autopsy/keywordsearch/dropdown-icon.png"))); settingsLabel.setIcon(new javax.swing.ImageIcon(
getClass().getResource("/org/sleuthkit/autopsy/keywordsearch/dropdown-icon.png")));
}//GEN-LAST:event_settingsLabelMouseExited }//GEN-LAST:event_settingsLabelMouseExited
// Variables declaration - do not modify//GEN-BEGIN:variables // Variables declaration - do not modify//GEN-BEGIN:variables
private javax.swing.JMenuItem copyMenuItem; private javax.swing.JMenuItem copyMenuItem;
private javax.swing.JMenuItem cutMenuItem; private javax.swing.JMenuItem cutMenuItem;
@ -405,11 +433,9 @@ class KeywordSearchPanel extends AbstractKeywordSearchPerformer {
final int numIndexedFiles = KeywordSearch.getServer().queryNumIndexedFiles(); final int numIndexedFiles = KeywordSearch.getServer().queryNumIndexedFiles();
KeywordSearch.fireNumIndexedFilesChange(null, new Integer(numIndexedFiles)); KeywordSearch.fireNumIndexedFilesChange(null, new Integer(numIndexedFiles));
//setFilesIndexed(numIndexedFiles); //setFilesIndexed(numIndexedFiles);
} } catch (NoOpenCoreException ex) {
catch (NoOpenCoreException ex) {
logger.log(Level.SEVERE, "Error executing Solr query, " + ex); logger.log(Level.SEVERE, "Error executing Solr query, " + ex);
} } catch (KeywordSearchModuleException se) {
catch (KeywordSearchModuleException se) {
logger.log(Level.SEVERE, "Error executing Solr query, " + se.getMessage()); logger.log(Level.SEVERE, "Error executing Solr query, " + se.getMessage());
} }
break; break;

View File

@ -25,43 +25,48 @@ import java.util.List;
* KeywordSearchPerformers are perform different searches from * KeywordSearchPerformers are perform different searches from
* different interfaces and places in the application. Its * different interfaces and places in the application. Its
* results are then passed to a KeywordSearchQuery implementation * results are then passed to a KeywordSearchQuery implementation
* to perform the actual search. * to perform the actual search.
*/ */
interface KeywordSearchPerformerInterface { interface KeywordSearchPerformerInterface {
/** /**
* Does this interface support multi-word queries? * Does this interface support multi-word queries?
* @return *
* @return
*/ */
boolean isMultiwordQuery(); boolean isMultiwordQuery();
/** /**
* True if the user did not choose to do a regular expression search * True if the user did not choose to do a regular expression search
* @return *
* @return
*/ */
boolean isLuceneQuerySelected(); boolean isLuceneQuerySelected();
/** /**
* Returns the query/keyword string that the user entered/selected * Returns the query/keyword string that the user entered/selected
*
* @return Keyword to search * @return Keyword to search
*/ */
String getQueryText(); String getQueryText();
/** /**
* Returns the list of Keyword objects that the user entered/selected * Returns the list of Keyword objects that the user entered/selected
* @return *
* @return
*/ */
List<Keyword> getQueryList(); List<Keyword> getQueryList();
/** /**
* Set the number of files that have been indexed * Set the number of files that have been indexed
* @param filesIndexed *
* @param filesIndexed
*/ */
void setFilesIndexed(int filesIndexed); void setFilesIndexed(int filesIndexed);
/** /**
* Performs the search using the selected keywords. * Performs the search using the selected keywords.
* Creates a DataResultTopComponent with the results. * Creates a DataResultTopComponent with the results.
*/ */
void search(); void search();
} }

View File

@ -21,92 +21,99 @@ package org.sleuthkit.autopsy.keywordsearch;
import java.util.Collection; import java.util.Collection;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import org.apache.solr.client.solrj.response.TermsResponse.Term; import org.apache.solr.client.solrj.response.TermsResponse.Term;
import org.sleuthkit.datamodel.AbstractFile; import org.sleuthkit.datamodel.AbstractFile;
/** /**
* Interface for a search query. Implemented by various * Interface for a search query. Implemented by various
* engines or methods of using the same engine. One of these * engines or methods of using the same engine. One of these
* is created for each query. * is created for each query.
*/ */
interface KeywordSearchQuery { interface KeywordSearchQuery {
/** /**
* validate the query pre execution * validate the query pre execution
*
* @return true if the query passed validation * @return true if the query passed validation
*/ */
public boolean validate(); public boolean validate();
/** /**
* execute query and return results without publishing them * execute query and return results without publishing them
* return results for all matching terms * return results for all matching terms
*
* @return
* @throws NoOpenCoreException if query failed due to server error, this could be a notification to stop processing * @throws NoOpenCoreException if query failed due to server error, this could be a notification to stop processing
* @return
*/ */
public Map<String,List<ContentHit>> performQuery() throws NoOpenCoreException; public Map<String, List<ContentHit>> performQuery() throws NoOpenCoreException;
/** /**
* Set an optional filter to narrow down the search * Set an optional filter to narrow down the search
* Adding multiple filters ANDs them together. * Adding multiple filters ANDs them together.
* For OR, add multiple ids to a single filter * For OR, add multiple ids to a single filter
*
* @param filter filter to set on the query * @param filter filter to set on the query
*/ */
public void addFilter(KeywordQueryFilter filter); public void addFilter(KeywordQueryFilter filter);
/** /**
* Set an optional SOLR field to narrow down the search * Set an optional SOLR field to narrow down the search
*
* @param field field to set on the query * @param field field to set on the query
*/ */
public void setField(String field); public void setField(String field);
/** /**
* escape the query string and use the escaped string in the query * escape the query string and use the escaped string in the query
*/ */
public void escape(); public void escape();
/** /**
*
* @return true if query was escaped * @return true if query was escaped
*/ */
public boolean isEscaped(); public boolean isEscaped();
/** /**
*
* @return true if query is a literal query (non regex) * @return true if query is a literal query (non regex)
*/ */
public boolean isLiteral(); public boolean isLiteral();
/** /**
* return original keyword/query string * return original keyword/query string
*
* @return the query String supplied originally * @return the query String supplied originally
*/ */
public String getQueryString(); public String getQueryString();
/** /**
* return escaped keyword/query string if escaping was done * return escaped keyword/query string if escaping was done
*
* @return the escaped query string, or original string if no escaping done * @return the escaped query string, or original string if no escaping done
*/ */
public String getEscapedQueryString(); public String getEscapedQueryString();
/** /**
* get terms associated with the query if any * get terms associated with the query if any
*
* @return collection of terms associated with the query * @return collection of terms associated with the query
*/ */
public Collection<Term>getTerms(); public Collection<Term> getTerms();
/** /**
* write results to blackboard per single term and file hit * write results to blackboard per single term and file hit
* this method is useful if something else should keep track of partial results to write * this method is useful if something else should keep track of partial results to write
* @param termHit term for only which to write results *
* @param termHit term for only which to write results
* @param newFsHit AbstractFile for which to write results for this hit * @param newFsHit AbstractFile for which to write results for this hit
* @param snippet snippet preview with hit context, or null if there is no snippet * @param snippet snippet preview with hit context, or null if there is no snippet
* @param listName listname * @param listName listname
* @return collection of results (with cached bb artifacts/attributes) created and written * @return collection of results (with cached bb artifacts/attributes) created and written
*/ */
public KeywordWriteResult writeToBlackBoard(String termHit, AbstractFile newFsHit, String snippet, String listName); public KeywordWriteResult writeToBlackBoard(String termHit, AbstractFile newFsHit, String snippet, String listName);
} }

View File

@ -36,17 +36,18 @@ import org.sleuthkit.autopsy.keywordsearch.KeywordSearch.QueryType;
/** /**
* Responsible for running a keyword search query and displaying * Responsible for running a keyword search query and displaying
* the results. * the results.
*/ */
class KeywordSearchQueryManager { class KeywordSearchQueryManager {
// how to display the results // how to display the results
public enum Presentation { public enum Presentation {
FLAT, // all results are in a single level (even if multiple keywords and reg-exps are used). We made this because we were having problems with multiple-levels of nodes and the thumbnail and table view sharing an ExplorerManager. IconView seemed to change EM so that it did not allow lower levels to be selected. FLAT,
// all results are in a single level (even if multiple keywords and reg-exps are used). We made this because we were having problems with multiple-levels of nodes and the thumbnail and table view sharing an ExplorerManager. IconView seemed to change EM so that it did not allow lower levels to be selected.
COLLAPSE, // two levels. Keywords on top, files on bottom. COLLAPSE, // two levels. Keywords on top, files on bottom.
DETAIL // not currently used, but seems like it has three levels of nodes DETAIL // not currently used, but seems like it has three levels of nodes
}; };
private List<Keyword> keywords; private List<Keyword> keywords;
private Presentation presentation; private Presentation presentation;
private List<KeywordSearchQuery> queryDelegates; private List<KeywordSearchQuery> queryDelegates;
@ -55,8 +56,7 @@ class KeywordSearchQueryManager {
private static Logger logger = Logger.getLogger(KeywordSearchQueryManager.class.getName()); private static Logger logger = Logger.getLogger(KeywordSearchQueryManager.class.getName());
/** /**
* * @param queries Keywords to search for
* @param queries Keywords to search for
* @param presentation Presentation layout * @param presentation Presentation layout
*/ */
public KeywordSearchQueryManager(List<Keyword> queries, Presentation presentation) { public KeywordSearchQueryManager(List<Keyword> queries, Presentation presentation) {
@ -67,9 +67,8 @@ class KeywordSearchQueryManager {
} }
/** /**
* * @param query Keyword to search for
* @param query Keyword to search for * @param qt Query type
* @param qt Query type
* @param presentation Presentation Layout * @param presentation Presentation Layout
*/ */
public KeywordSearchQueryManager(String query, QueryType qt, Presentation presentation) { public KeywordSearchQueryManager(String query, QueryType qt, Presentation presentation) {
@ -81,9 +80,8 @@ class KeywordSearchQueryManager {
} }
/** /**
* * @param query Keyword to search for
* @param query Keyword to search for * @param isLiteral false if reg-exp
* @param isLiteral false if reg-exp
* @param presentation Presentation layout * @param presentation Presentation layout
*/ */
public KeywordSearchQueryManager(String query, boolean isLiteral, Presentation presentation) { public KeywordSearchQueryManager(String query, boolean isLiteral, Presentation presentation) {
@ -138,7 +136,7 @@ class KeywordSearchQueryManager {
// q.execute(); // q.execute();
// } // }
// } else { // } else {
//Collapsed view //Collapsed view
Collection<KeyValueQuery> things = new ArrayList<>(); Collection<KeyValueQuery> things = new ArrayList<>();
int queryID = 0; int queryID = 0;
@ -154,11 +152,14 @@ class KeywordSearchQueryManager {
String queryConcatStr = queryConcat.toString(); String queryConcatStr = queryConcat.toString();
final int queryConcatStrLen = queryConcatStr.length(); final int queryConcatStrLen = queryConcatStr.length();
final String queryStrShort = queryConcatStrLen > 15 ? queryConcatStr.substring(0, 14) + "..." : queryConcatStr; final String queryStrShort = queryConcatStrLen > 15 ? queryConcatStr.substring(0, 14) + "..." : queryConcatStr;
final String windowTitle = NbBundle.getMessage(this.getClass(), "KeywordSearchQueryManager.execute.exeWinTitle", ++resultWindowCount, queryStrShort); final String windowTitle = NbBundle
.getMessage(this.getClass(), "KeywordSearchQueryManager.execute.exeWinTitle", ++resultWindowCount,
queryStrShort);
DataResultTopComponent searchResultWin = DataResultTopComponent.createInstance(windowTitle); DataResultTopComponent searchResultWin = DataResultTopComponent.createInstance(windowTitle);
if (things.size() > 0) { if (things.size() > 0) {
Children childThingNodes = Children childThingNodes =
Children.create(new KeywordSearchResultFactory(keywords, things, presentation, searchResultWin), true); Children.create(new KeywordSearchResultFactory(keywords, things, presentation, searchResultWin),
true);
rootNode = new AbstractNode(childThingNodes); rootNode = new AbstractNode(childThingNodes);
} else { } else {
@ -175,6 +176,7 @@ class KeywordSearchQueryManager {
/** /**
* validate the queries before they are run * validate the queries before they are run
*
* @return false if any are invalid * @return false if any are invalid
*/ */
public boolean validate() { public boolean validate() {

View File

@ -27,9 +27,12 @@ import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.concurrent.locks.ReentrantReadWriteLock; import java.util.concurrent.locks.ReentrantReadWriteLock;
import java.util.logging.Level; import java.util.logging.Level;
import org.sleuthkit.autopsy.coreutils.Logger; import org.sleuthkit.autopsy.coreutils.Logger;
import javax.swing.SwingUtilities; import javax.swing.SwingUtilities;
import javax.swing.SwingWorker; import javax.swing.SwingWorker;
import org.netbeans.api.progress.ProgressHandle; import org.netbeans.api.progress.ProgressHandle;
import org.netbeans.api.progress.ProgressHandleFactory; import org.netbeans.api.progress.ProgressHandleFactory;
import org.openide.nodes.ChildFactory; import org.openide.nodes.ChildFactory;
@ -54,7 +57,6 @@ import org.sleuthkit.datamodel.FsContent;
import org.sleuthkit.datamodel.TskData.TSK_DB_FILES_TYPE_ENUM; import org.sleuthkit.datamodel.TskData.TSK_DB_FILES_TYPE_ENUM;
/** /**
*
* factory produces top level nodes with query * factory produces top level nodes with query
* responsible for assembling nodes and columns in the right way * responsible for assembling nodes and columns in the right way
* and performing lazy queries as needed * and performing lazy queries as needed
@ -66,41 +68,41 @@ class KeywordSearchResultFactory extends ChildFactory<KeyValueQuery> {
public static enum CommonPropertyTypes { public static enum CommonPropertyTypes {
KEYWORD { KEYWORD {
@Override @Override
public String toString() { public String toString() {
return BlackboardAttribute.ATTRIBUTE_TYPE.TSK_KEYWORD.getDisplayName(); return BlackboardAttribute.ATTRIBUTE_TYPE.TSK_KEYWORD.getDisplayName();
} }
}, },
REGEX { REGEX {
@Override @Override
public String toString() { public String toString() {
return BlackboardAttribute.ATTRIBUTE_TYPE.TSK_KEYWORD_REGEXP.getDisplayName(); return BlackboardAttribute.ATTRIBUTE_TYPE.TSK_KEYWORD_REGEXP.getDisplayName();
} }
}, },
CONTEXT { CONTEXT {
@Override @Override
public String toString() { public String toString() {
return BlackboardAttribute.ATTRIBUTE_TYPE.TSK_KEYWORD_PREVIEW.getDisplayName(); return BlackboardAttribute.ATTRIBUTE_TYPE.TSK_KEYWORD_PREVIEW.getDisplayName();
} }
}, },
} }
private final Presentation presentation; private final Presentation presentation;
private List<Keyword> queries; private List<Keyword> queries;
private Collection<KeyValueQuery> things; private Collection<KeyValueQuery> things;
private final DataResultTopComponent viewer; //viewer driving this child node factory private final DataResultTopComponent viewer; //viewer driving this child node factory
private static final Logger logger = Logger.getLogger(KeywordSearchResultFactory.class.getName()); private static final Logger logger = Logger.getLogger(KeywordSearchResultFactory.class.getName());
KeywordSearchResultFactory(List<Keyword> queries, Collection<KeyValueQuery> things, Presentation presentation, DataResultTopComponent viewer) { KeywordSearchResultFactory(List<Keyword> queries, Collection<KeyValueQuery> things, Presentation presentation,
DataResultTopComponent viewer) {
this.queries = queries; this.queries = queries;
this.things = things; this.things = things;
this.presentation = presentation; this.presentation = presentation;
this.viewer = viewer; this.viewer = viewer;
} }
KeywordSearchResultFactory(Keyword query, Collection<KeyValueQuery> things, Presentation presentation, DataResultTopComponent viewer) { KeywordSearchResultFactory(Keyword query, Collection<KeyValueQuery> things, Presentation presentation,
DataResultTopComponent viewer) {
queries = new ArrayList<>(); queries = new ArrayList<>();
queries.add(query); queries.add(query);
this.presentation = presentation; this.presentation = presentation;
@ -109,9 +111,10 @@ class KeywordSearchResultFactory extends ChildFactory<KeyValueQuery> {
} }
/** /**
* call this at least for the parent Node, to make sure all common * call this at least for the parent Node, to make sure all common
* properties are displayed as columns (since we are doing lazy child Node load * properties are displayed as columns (since we are doing lazy child Node load
* we need to preinitialize properties when sending parent Node) * we need to preinitialize properties when sending parent Node)
*
* @param toSet property set map for a Node * @param toSet property set map for a Node
*/ */
public static void initCommonProperties(Map<String, Object> toSet) { public static void initCommonProperties(Map<String, Object> toSet) {
@ -121,7 +124,8 @@ class KeywordSearchResultFactory extends ChildFactory<KeyValueQuery> {
toSet.put(commonTypes[i].toString(), ""); toSet.put(commonTypes[i].toString(), "");
} }
AbstractAbstractFileNode.AbstractFilePropertyType[] fsTypes = AbstractAbstractFileNode.AbstractFilePropertyType.values(); AbstractAbstractFileNode.AbstractFilePropertyType[] fsTypes = AbstractAbstractFileNode.AbstractFilePropertyType
.values();
final int FS_PROPS_LEN = fsTypes.length; final int FS_PROPS_LEN = fsTypes.length;
for (int i = 0; i < FS_PROPS_LEN; ++i) { for (int i = 0; i < FS_PROPS_LEN; ++i) {
toSet.put(fsTypes[i].toString(), ""); toSet.put(fsTypes[i].toString(), "");
@ -150,9 +154,8 @@ class KeywordSearchResultFactory extends ChildFactory<KeyValueQuery> {
setCommonProperty(map, CommonPropertyTypes.REGEX, Boolean.valueOf(!thing.getQuery().isEscaped())); setCommonProperty(map, CommonPropertyTypes.REGEX, Boolean.valueOf(!thing.getQuery().isEscaped()));
ResultCollapsedChildFactory childFactory = new ResultCollapsedChildFactory(thing); ResultCollapsedChildFactory childFactory = new ResultCollapsedChildFactory(thing);
childFactory.createKeysForFlatNodes(toPopulate); childFactory.createKeysForFlatNodes(toPopulate);
} }
} } else if (presentation == Presentation.DETAIL) {
else if (presentation == Presentation.DETAIL) {
Iterator<KeyValueQuery> it = things.iterator(); Iterator<KeyValueQuery> it = things.iterator();
for (Keyword keyword : queries) { for (Keyword keyword : queries) {
Map<String, Object> map = new LinkedHashMap<>(); Map<String, Object> map = new LinkedHashMap<>();
@ -176,7 +179,7 @@ class KeywordSearchResultFactory extends ChildFactory<KeyValueQuery> {
toPopulate.add(thing); toPopulate.add(thing);
} }
} }
return true; return true;
} }
@ -185,9 +188,8 @@ class KeywordSearchResultFactory extends ChildFactory<KeyValueQuery> {
ChildFactory<KeyValueQuery> childFactory; ChildFactory<KeyValueQuery> childFactory;
if (presentation == Presentation.FLAT) { if (presentation == Presentation.FLAT) {
ResultCollapsedChildFactory factory = new ResultCollapsedChildFactory(thing); ResultCollapsedChildFactory factory = new ResultCollapsedChildFactory(thing);
return factory.createFlatNodeForKey(thing); return factory.createFlatNodeForKey(thing);
} } else if (presentation == Presentation.COLLAPSE) {
else if (presentation == Presentation.COLLAPSE) {
childFactory = new ResultCollapsedChildFactory(thing); childFactory = new ResultCollapsedChildFactory(thing);
final Node ret = new KeyValueNode(thing, Children.create(childFactory, true)); final Node ret = new KeyValueNode(thing, Children.create(childFactory, true));
SwingUtilities.invokeLater(new Runnable() { SwingUtilities.invokeLater(new Runnable() {
@ -224,7 +226,7 @@ class KeywordSearchResultFactory extends ChildFactory<KeyValueQuery> {
public boolean createKeysForFlatNodes(List<KeyValueQuery> toPopulate) { public boolean createKeysForFlatNodes(List<KeyValueQuery> toPopulate) {
return createKeys(toPopulate); return createKeys(toPopulate);
} }
@Override @Override
protected boolean createKeys(List<KeyValueQuery> toPopulate) { protected boolean createKeys(List<KeyValueQuery> toPopulate) {
final KeyValueQuery queryThingQuery = queryThing; final KeyValueQuery queryThingQuery = queryThing;
@ -236,7 +238,7 @@ class KeywordSearchResultFactory extends ChildFactory<KeyValueQuery> {
} }
List<KeyValueQuery> tempList = new ArrayList<>(); List<KeyValueQuery> tempList = new ArrayList<>();
//execute the query and get fscontents matching //execute the query and get fscontents matching
Map<String, List<ContentHit>> tcqRes; Map<String, List<ContentHit>> tcqRes;
try { try {
@ -249,7 +251,8 @@ class KeywordSearchResultFactory extends ChildFactory<KeyValueQuery> {
//get listname //get listname
String listName = ""; String listName = "";
KeywordSearchListsAbstract.KeywordSearchList list = KeywordSearchListsXML.getCurrent().getListWithKeyword(tcq.getQueryString()); KeywordSearchListsAbstract.KeywordSearchList list = KeywordSearchListsXML.getCurrent().getListWithKeyword(
tcq.getQueryString());
if (list != null) { if (list != null) {
listName = list.getName(); listName = list.getName();
} }
@ -264,7 +267,7 @@ class KeywordSearchResultFactory extends ChildFactory<KeyValueQuery> {
try { try {
String snippet; String snippet;
String snippetQuery = null; String snippetQuery = null;
if (literal_query) { if (literal_query) {
@ -305,13 +308,14 @@ class KeywordSearchResultFactory extends ChildFactory<KeyValueQuery> {
} }
final String highlightQueryEscaped = getHighlightQuery(tcq, literal_query, tcqRes, f); final String highlightQueryEscaped = getHighlightQuery(tcq, literal_query, tcqRes, f);
tempList.add(new KeyValueQueryContent(f.getName(), resMap, ++resID, f, highlightQueryEscaped, tcq, previewChunk, tcqRes)); tempList.add(new KeyValueQueryContent(f.getName(), resMap, ++resID, f, highlightQueryEscaped, tcq,
previewChunk, tcqRes));
} }
// Add all the nodes to toPopulate at once. Minimizes node creation // Add all the nodes to toPopulate at once. Minimizes node creation
// EDT threads, which can slow and/or hang the UI on large queries. // EDT threads, which can slow and/or hang the UI on large queries.
toPopulate.addAll(tempList); toPopulate.addAll(tempList);
//write to bb //write to bb
//cannot reuse snippet in ResultWriter //cannot reuse snippet in ResultWriter
//because for regex searches in UI we compress results by showing a file per regex once (even if multiple term hits) //because for regex searches in UI we compress results by showing a file per regex once (even if multiple term hits)
@ -321,7 +325,8 @@ class KeywordSearchResultFactory extends ChildFactory<KeyValueQuery> {
return true; return true;
} }
private String getHighlightQuery(KeywordSearchQuery tcq, boolean literal_query, Map<String, List<ContentHit>> tcqRes, AbstractFile f) { private String getHighlightQuery(KeywordSearchQuery tcq, boolean literal_query,
Map<String, List<ContentHit>> tcqRes, AbstractFile f) {
String highlightQueryEscaped; String highlightQueryEscaped;
if (literal_query) { if (literal_query) {
//literal, treat as non-regex, non-term component query //literal, treat as non-regex, non-term component query
@ -377,8 +382,8 @@ class KeywordSearchResultFactory extends ChildFactory<KeyValueQuery> {
// @@@ This method is a workaround until we decide whether we need all three presentation modes or FLAT is sufficient. // @@@ This method is a workaround until we decide whether we need all three presentation modes or FLAT is sufficient.
public Node createFlatNodeForKey(KeyValueQuery thing) { public Node createFlatNodeForKey(KeyValueQuery thing) {
return createNodeForKey(thing); return createNodeForKey(thing);
} }
@Override @Override
protected Node createNodeForKey(KeyValueQuery thing) { protected Node createNodeForKey(KeyValueQuery thing) {
final KeyValueQueryContent thingContent = (KeyValueQueryContent) thing; final KeyValueQueryContent thingContent = (KeyValueQueryContent) thing;
@ -389,7 +394,9 @@ class KeywordSearchResultFactory extends ChildFactory<KeyValueQuery> {
Node kvNode = new KeyValueNode(thingContent, Children.LEAF, Lookups.singleton(content)); Node kvNode = new KeyValueNode(thingContent, Children.LEAF, Lookups.singleton(content));
//wrap in KeywordSearchFilterNode for the markup content, might need to override FilterNode for more customization //wrap in KeywordSearchFilterNode for the markup content, might need to override FilterNode for more customization
HighlightedMatchesSource highlights = new HighlightedMatchesSource(content, queryStr, !thingContent.getQuery().isEscaped(), false, hits); HighlightedMatchesSource highlights = new HighlightedMatchesSource(content, queryStr,
!thingContent.getQuery().isEscaped(),
false, hits);
return new KeywordSearchFilterNode(highlights, kvNode, queryStr, previewChunk); return new KeywordSearchFilterNode(highlights, kvNode, queryStr, previewChunk);
} }
} }
@ -448,22 +455,24 @@ class KeywordSearchResultFactory extends ChildFactory<KeyValueQuery> {
int resID = 0; int resID = 0;
final KeywordSearchQuery origQuery = thing.getQuery(); final KeywordSearchQuery origQuery = thing.getQuery();
List<KeyValueQuery> tempList = new ArrayList<>(); List<KeyValueQuery> tempList = new ArrayList<>();
for (final AbstractFile f : uniqueMatches.keySet()) { for (final AbstractFile f : uniqueMatches.keySet()) {
final int previewChunkId = uniqueMatches.get(f); final int previewChunkId = uniqueMatches.get(f);
Map<String, Object> resMap = new LinkedHashMap<>(); Map<String, Object> resMap = new LinkedHashMap<>();
if (f.getType() == TSK_DB_FILES_TYPE_ENUM.FS) { if (f.getType() == TSK_DB_FILES_TYPE_ENUM.FS) {
AbstractFsContentNode.fillPropertyMap(resMap, (FsContent) f); AbstractFsContentNode.fillPropertyMap(resMap, (FsContent) f);
} }
tempList.add(new KeyValueQueryContent(f.getName(), resMap, ++resID, f, keywordQuery, thing.getQuery(), previewChunkId, matchesRes)); tempList.add(
new KeyValueQueryContent(f.getName(), resMap, ++resID, f, keywordQuery, thing.getQuery(),
previewChunkId, matchesRes));
} }
// Add all the nodes to toPopulate at once. Minimizes node creation // Add all the nodes to toPopulate at once. Minimizes node creation
// EDT threads, which can slow and/or hang the UI on large queries. // EDT threads, which can slow and/or hang the UI on large queries.
toPopulate.addAll(tempList); toPopulate.addAll(tempList);
//write to bb //write to bb
new ResultWriter(matchesRes, origQuery, "").execute(); new ResultWriter(matchesRes, origQuery, "").execute();
@ -480,7 +489,9 @@ class KeywordSearchResultFactory extends ChildFactory<KeyValueQuery> {
Node kvNode = new KeyValueNode(thingContent, Children.LEAF, Lookups.singleton(content)); Node kvNode = new KeyValueNode(thingContent, Children.LEAF, Lookups.singleton(content));
//wrap in KeywordSearchFilterNode for the markup content //wrap in KeywordSearchFilterNode for the markup content
HighlightedMatchesSource highlights = new HighlightedMatchesSource(content, query, !thingContent.getQuery().isEscaped(), hits); HighlightedMatchesSource highlights = new HighlightedMatchesSource(content, query,
!thingContent.getQuery().isEscaped(),
hits);
return new KeywordSearchFilterNode(highlights, kvNode, query, previewChunk); return new KeywordSearchFilterNode(highlights, kvNode, query, previewChunk);
} }
} }
@ -512,7 +523,8 @@ class KeywordSearchResultFactory extends ChildFactory<KeyValueQuery> {
return hits; return hits;
} }
public KeyValueQueryContent(String name, Map<String, Object> map, int id, Content content, String queryStr, KeywordSearchQuery query, int previewChunk, Map<String, List<ContentHit>> hits) { public KeyValueQueryContent(String name, Map<String, Object> map, int id, Content content, String queryStr,
KeywordSearchQuery query, int previewChunk, Map<String, List<ContentHit>> hits) {
super(name, map, id, query); super(name, map, id, query);
this.content = content; this.content = content;
this.queryStr = queryStr; this.queryStr = queryStr;
@ -522,7 +534,7 @@ class KeywordSearchResultFactory extends ChildFactory<KeyValueQuery> {
} }
/** /**
* worker for writing results to bb, with progress bar, cancellation, * worker for writing results to bb, with progress bar, cancellation,
* and central registry of workers to be stopped when case is closed * and central registry of workers to be stopped when case is closed
*/ */
static class ResultWriter extends SwingWorker<Object, Void> { static class ResultWriter extends SwingWorker<Object, Void> {
@ -556,7 +568,8 @@ class KeywordSearchResultFactory extends ChildFactory<KeyValueQuery> {
}); });
if (!this.isCancelled() && !na.isEmpty()) { if (!this.isCancelled() && !na.isEmpty()) {
IngestServices.getDefault().fireModuleDataEvent(new ModuleDataEvent(KeywordSearchIngestModule.MODULE_NAME, ARTIFACT_TYPE.TSK_KEYWORD_HIT, na)); IngestServices.getDefault().fireModuleDataEvent(
new ModuleDataEvent(KeywordSearchIngestModule.MODULE_NAME, ARTIFACT_TYPE.TSK_KEYWORD_HIT, na));
} }
} }
@ -568,7 +581,8 @@ class KeywordSearchResultFactory extends ChildFactory<KeyValueQuery> {
//writerLock.lock(); //writerLock.lock();
try { try {
final String queryStr = query.getQueryString(); final String queryStr = query.getQueryString();
final String queryDisp = queryStr.length() > QUERY_DISPLAY_LEN ? queryStr.substring(0, QUERY_DISPLAY_LEN - 1) + " ..." : queryStr; final String queryDisp = queryStr.length() > QUERY_DISPLAY_LEN ?
queryStr.substring(0, QUERY_DISPLAY_LEN - 1) + " ..." : queryStr;
progress = ProgressHandleFactory.createHandle("Saving results: " + queryDisp, new Cancellable() { progress = ProgressHandleFactory.createHandle("Saving results: " + queryDisp, new Cancellable() {
@Override @Override
@ -590,7 +604,8 @@ class KeywordSearchResultFactory extends ChildFactory<KeyValueQuery> {
final String snippetQuery = KeywordSearchUtil.escapeLuceneQuery(hit); final String snippetQuery = KeywordSearchUtil.escapeLuceneQuery(hit);
String snippet; String snippet;
try { try {
snippet = LuceneQuery.querySnippet(snippetQuery, f.getId(), chunkId, !query.isLiteral(), true); snippet = LuceneQuery
.querySnippet(snippetQuery, f.getId(), chunkId, !query.isLiteral(), true);
} catch (NoOpenCoreException e) { } catch (NoOpenCoreException e) {
logger.log(Level.WARNING, "Error querying snippet: " + snippetQuery, e); logger.log(Level.WARNING, "Error querying snippet: " + snippetQuery, e);
//no reason to continie //no reason to continie

View File

@ -25,6 +25,7 @@ import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.logging.Level; import java.util.logging.Level;
import org.sleuthkit.autopsy.coreutils.Logger; import org.sleuthkit.autopsy.coreutils.Logger;
import org.sleuthkit.autopsy.coreutils.ModuleSettings; import org.sleuthkit.autopsy.coreutils.ModuleSettings;
import org.sleuthkit.autopsy.coreutils.StringExtract; import org.sleuthkit.autopsy.coreutils.StringExtract;
@ -35,105 +36,111 @@ import org.sleuthkit.autopsy.keywordsearch.KeywordSearchIngestModule.UpdateFrequ
//This file contains constants and settings for KeywordSearch //This file contains constants and settings for KeywordSearch
class KeywordSearchSettings { class KeywordSearchSettings {
public static final String MODULE_NAME = "KeywordSearch"; public static final String MODULE_NAME = "KeywordSearch";
static final String PROPERTIES_OPTIONS = MODULE_NAME+"_Options"; static final String PROPERTIES_OPTIONS = MODULE_NAME + "_Options";
static final String PROPERTIES_NSRL = MODULE_NAME+"_NSRL"; static final String PROPERTIES_NSRL = MODULE_NAME + "_NSRL";
static final String PROPERTIES_SCRIPTS = MODULE_NAME+"_Scripts"; static final String PROPERTIES_SCRIPTS = MODULE_NAME + "_Scripts";
private static boolean skipKnown = true; private static boolean skipKnown = true;
private static final Logger logger = Logger.getLogger(KeywordSearchSettings.class.getName()); private static final Logger logger = Logger.getLogger(KeywordSearchSettings.class.getName());
private static UpdateFrequency UpdateFreq = UpdateFrequency.DEFAULT; private static UpdateFrequency UpdateFreq = UpdateFrequency.DEFAULT;
private static List<StringExtract.StringExtractUnicodeTable.SCRIPT> stringExtractScripts = new ArrayList<StringExtract.StringExtractUnicodeTable.SCRIPT>(); private static List<StringExtract.StringExtractUnicodeTable.SCRIPT> stringExtractScripts
private static Map<String,String> stringExtractOptions = new HashMap<String,String>(); = new ArrayList<StringExtract.StringExtractUnicodeTable.SCRIPT>();
private static Map<String, String> stringExtractOptions = new HashMap<String, String>();
/** /**
* Gets the update Frequency from KeywordSearch_Options.properties * Gets the update Frequency from KeywordSearch_Options.properties
*
* @return KeywordSearchIngestModule's update frequency * @return KeywordSearchIngestModule's update frequency
*/ */
static UpdateFrequency getUpdateFrequency(){ static UpdateFrequency getUpdateFrequency() {
if(ModuleSettings.getConfigSetting(PROPERTIES_OPTIONS, "UpdateFrequency") != null){ if (ModuleSettings.getConfigSetting(PROPERTIES_OPTIONS, "UpdateFrequency") != null) {
return UpdateFrequency.valueOf(ModuleSettings.getConfigSetting(PROPERTIES_OPTIONS, "UpdateFrequency")); return UpdateFrequency.valueOf(ModuleSettings.getConfigSetting(PROPERTIES_OPTIONS, "UpdateFrequency"));
} }
//if it failed, return the default/last known value //if it failed, return the default/last known value
logger.log(Level.WARNING, "Could not read property for UpdateFrequency, returning backup value."); logger.log(Level.WARNING, "Could not read property for UpdateFrequency, returning backup value.");
return UpdateFrequency.DEFAULT; return UpdateFrequency.DEFAULT;
} }
/** /**
* Sets the update frequency and writes to KeywordSearch_Options.properties * Sets the update frequency and writes to KeywordSearch_Options.properties
*
* @param freq Sets KeywordSearchIngestModule to this value. * @param freq Sets KeywordSearchIngestModule to this value.
*/ */
static void setUpdateFrequency(UpdateFrequency freq){ static void setUpdateFrequency(UpdateFrequency freq) {
ModuleSettings.setConfigSetting(PROPERTIES_OPTIONS, "UpdateFrequency", freq.name()); ModuleSettings.setConfigSetting(PROPERTIES_OPTIONS, "UpdateFrequency", freq.name());
UpdateFreq = freq; UpdateFreq = freq;
} }
/** /**
* Sets whether or not to skip adding known good files to the search during index. * Sets whether or not to skip adding known good files to the search during index.
* @param skip *
* @param skip
*/ */
static void setSkipKnown(boolean skip) { static void setSkipKnown(boolean skip) {
ModuleSettings.setConfigSetting(PROPERTIES_NSRL, "SkipKnown", Boolean.toString(skip)); ModuleSettings.setConfigSetting(PROPERTIES_NSRL, "SkipKnown", Boolean.toString(skip));
skipKnown = skip; skipKnown = skip;
} }
/** /**
* Gets the setting for whether or not this ingest is skipping adding known good files to the index. * Gets the setting for whether or not this ingest is skipping adding known good files to the index.
*
* @return skip setting * @return skip setting
*/ */
static boolean getSkipKnown() { static boolean getSkipKnown() {
if(ModuleSettings.getConfigSetting(PROPERTIES_NSRL, "SkipKnown") != null){ if (ModuleSettings.getConfigSetting(PROPERTIES_NSRL, "SkipKnown") != null) {
return Boolean.parseBoolean(ModuleSettings.getConfigSetting(PROPERTIES_NSRL, "SkipKnown")); return Boolean.parseBoolean(ModuleSettings.getConfigSetting(PROPERTIES_NSRL, "SkipKnown"));
} }
//if it fails, return the default/last known value //if it fails, return the default/last known value
logger.log(Level.WARNING, "Could not read property for SkipKnown, returning backup value."); logger.log(Level.WARNING, "Could not read property for SkipKnown, returning backup value.");
return skipKnown; return skipKnown;
} }
/** /**
* Sets what scripts to extract during ingest * Sets what scripts to extract during ingest
*
* @param scripts List of scripts to extract * @param scripts List of scripts to extract
*/ */
static void setStringExtractScripts(List<StringExtract.StringExtractUnicodeTable.SCRIPT> scripts) { static void setStringExtractScripts(List<StringExtract.StringExtractUnicodeTable.SCRIPT> scripts) {
stringExtractScripts.clear(); stringExtractScripts.clear();
stringExtractScripts.addAll(scripts); stringExtractScripts.addAll(scripts);
//Disabling scripts that weren't selected //Disabling scripts that weren't selected
for(String s : ModuleSettings.getConfigSettings(PROPERTIES_SCRIPTS).keySet()){ for (String s : ModuleSettings.getConfigSettings(PROPERTIES_SCRIPTS).keySet()) {
if (! scripts.contains(StringExtract.StringExtractUnicodeTable.SCRIPT.valueOf(s))){ if (!scripts.contains(StringExtract.StringExtractUnicodeTable.SCRIPT.valueOf(s))) {
ModuleSettings.setConfigSetting(PROPERTIES_SCRIPTS, s, "false"); ModuleSettings.setConfigSetting(PROPERTIES_SCRIPTS, s, "false");
} }
} }
//Writing and enabling selected scripts //Writing and enabling selected scripts
for(StringExtract.StringExtractUnicodeTable.SCRIPT s : stringExtractScripts){ for (StringExtract.StringExtractUnicodeTable.SCRIPT s : stringExtractScripts) {
ModuleSettings.setConfigSetting(PROPERTIES_SCRIPTS, s.name(), "true"); ModuleSettings.setConfigSetting(PROPERTIES_SCRIPTS, s.name(), "true");
} }
} }
/** /**
* Set / override string extract option * Set / override string extract option
*
* @param key option name to set * @param key option name to set
* @param val option value to set * @param val option value to set
*/ */
static void setStringExtractOption(String key, String val) { static void setStringExtractOption(String key, String val) {
stringExtractOptions.put(key, val); stringExtractOptions.put(key, val);
ModuleSettings.setConfigSetting(PROPERTIES_OPTIONS, key, val); ModuleSettings.setConfigSetting(PROPERTIES_OPTIONS, key, val);
} }
/** /**
* gets the currently set scripts to use * gets the currently set scripts to use
* *
* @return the list of currently used script * @return the list of currently used script
*/ */
static List<SCRIPT> getStringExtractScripts(){ static List<SCRIPT> getStringExtractScripts() {
if(ModuleSettings.getConfigSettings(PROPERTIES_SCRIPTS) != null && !ModuleSettings.getConfigSettings(PROPERTIES_SCRIPTS).isEmpty()){ if (ModuleSettings.getConfigSettings(PROPERTIES_SCRIPTS) != null && !ModuleSettings
.getConfigSettings(PROPERTIES_SCRIPTS).isEmpty()) {
List<SCRIPT> scripts = new ArrayList<SCRIPT>(); List<SCRIPT> scripts = new ArrayList<SCRIPT>();
for(Map.Entry<String,String> kvp : ModuleSettings.getConfigSettings(PROPERTIES_SCRIPTS).entrySet()){ for (Map.Entry<String, String> kvp : ModuleSettings.getConfigSettings(PROPERTIES_SCRIPTS).entrySet()) {
if(kvp.getValue().equals("true")){ if (kvp.getValue().equals("true")) {
scripts.add(SCRIPT.valueOf(kvp.getKey())); scripts.add(SCRIPT.valueOf(kvp.getKey()));
} }
} }
@ -143,72 +150,77 @@ class KeywordSearchSettings {
logger.log(Level.WARNING, "Could not read properties for extracting scripts, returning backup values."); logger.log(Level.WARNING, "Could not read properties for extracting scripts, returning backup values.");
return new ArrayList<SCRIPT>(stringExtractScripts); return new ArrayList<SCRIPT>(stringExtractScripts);
} }
/** /**
* get string extract option for the key * get string extract option for the key
*
* @param key option name * @param key option name
* @return option string value, or empty string if the option is not set * @return option string value, or empty string if the option is not set
*/ */
static String getStringExtractOption(String key) { static String getStringExtractOption(String key) {
if (ModuleSettings.getConfigSetting(PROPERTIES_OPTIONS, key) != null){ if (ModuleSettings.getConfigSetting(PROPERTIES_OPTIONS, key) != null) {
return ModuleSettings.getConfigSetting(PROPERTIES_OPTIONS, key); return ModuleSettings.getConfigSetting(PROPERTIES_OPTIONS, key);
} } else {
else { logger.log(Level.WARNING, "Could not read property for key " + key + ", returning backup value.");
logger.log(Level.WARNING, "Could not read property for key "+ key + ", returning backup value.");
return stringExtractOptions.get(key); return stringExtractOptions.get(key);
} }
} }
/** /**
* get the map of string extract options. * get the map of string extract options.
*
* @return Map<String,String> of extract options. * @return Map<String,String> of extract options.
*/ */
static Map<String,String> getStringExtractOptions(){ static Map<String, String> getStringExtractOptions() {
Map<String,String> settings = ModuleSettings.getConfigSettings(PROPERTIES_OPTIONS); Map<String, String> settings = ModuleSettings.getConfigSettings(PROPERTIES_OPTIONS);
if(settings == null){ if (settings == null) {
Map<String,String> settingsv2 = new HashMap<String,String>(); Map<String, String> settingsv2 = new HashMap<String, String>();
logger.log(Level.WARNING, "Could not read properties for " + PROPERTIES_OPTIONS + ".properties, returning backup values"); logger.log(Level.WARNING,
"Could not read properties for " + PROPERTIES_OPTIONS + ".properties, returning backup values");
settingsv2.putAll(stringExtractOptions); settingsv2.putAll(stringExtractOptions);
return settingsv2; return settingsv2;
} } else {
else {
return settings; return settings;
} }
} }
/** /**
* Sets the default values of the KeywordSearch properties files if none already exist. * Sets the default values of the KeywordSearch properties files if none already exist.
*/ */
static void setDefaults(){ static void setDefaults() {
logger.log(Level.INFO, "Detecting default settings."); logger.log(Level.INFO, "Detecting default settings.");
//setting default NSRL //setting default NSRL
if(!ModuleSettings.settingExists(KeywordSearchSettings.PROPERTIES_NSRL, "SkipKnown")){ if (!ModuleSettings.settingExists(KeywordSearchSettings.PROPERTIES_NSRL, "SkipKnown")) {
logger.log(Level.INFO, "No configuration for NSRL found, generating default..."); logger.log(Level.INFO, "No configuration for NSRL found, generating default...");
KeywordSearchSettings.setSkipKnown(true); KeywordSearchSettings.setSkipKnown(true);
} }
//setting default Update Frequency //setting default Update Frequency
if(!ModuleSettings.settingExists(KeywordSearchSettings.PROPERTIES_OPTIONS, "UpdateFrequency")){ if (!ModuleSettings.settingExists(KeywordSearchSettings.PROPERTIES_OPTIONS, "UpdateFrequency")) {
logger.log(Level.INFO, "No configuration for Update Frequency found, generating default..."); logger.log(Level.INFO, "No configuration for Update Frequency found, generating default...");
KeywordSearchSettings.setUpdateFrequency(UpdateFrequency.DEFAULT); KeywordSearchSettings.setUpdateFrequency(UpdateFrequency.DEFAULT);
} }
//setting default Extract UTF8 //setting default Extract UTF8
if(!ModuleSettings.settingExists(KeywordSearchSettings.PROPERTIES_OPTIONS, AbstractFileExtract.ExtractOptions.EXTRACT_UTF8.toString())){ if (!ModuleSettings.settingExists(KeywordSearchSettings.PROPERTIES_OPTIONS,
logger.log(Level.INFO, "No configuration for UTF8 found, generating default..."); AbstractFileExtract.ExtractOptions.EXTRACT_UTF8.toString())) {
KeywordSearchSettings.setStringExtractOption(AbstractFileExtract.ExtractOptions.EXTRACT_UTF8.toString(), Boolean.TRUE.toString()); logger.log(Level.INFO, "No configuration for UTF8 found, generating default...");
} KeywordSearchSettings.setStringExtractOption(AbstractFileExtract.ExtractOptions.EXTRACT_UTF8.toString(),
Boolean.TRUE.toString());
}
//setting default Extract UTF16 //setting default Extract UTF16
if(!ModuleSettings.settingExists(KeywordSearchSettings.PROPERTIES_OPTIONS, AbstractFileExtract.ExtractOptions.EXTRACT_UTF16.toString())){ if (!ModuleSettings.settingExists(KeywordSearchSettings.PROPERTIES_OPTIONS,
logger.log(Level.INFO, "No configuration for UTF16 found, generating defaults..."); AbstractFileExtract.ExtractOptions.EXTRACT_UTF16.toString())) {
KeywordSearchSettings.setStringExtractOption(AbstractFileExtract.ExtractOptions.EXTRACT_UTF16.toString(), Boolean.TRUE.toString()); logger.log(Level.INFO, "No configuration for UTF16 found, generating defaults...");
} KeywordSearchSettings.setStringExtractOption(AbstractFileExtract.ExtractOptions.EXTRACT_UTF16.toString(),
Boolean.TRUE.toString());
}
//setting default Latin-1 Script //setting default Latin-1 Script
if(!ModuleSettings.settingExists(KeywordSearchSettings.PROPERTIES_SCRIPTS, SCRIPT.LATIN_1.name())){ if (!ModuleSettings.settingExists(KeywordSearchSettings.PROPERTIES_SCRIPTS, SCRIPT.LATIN_1.name())) {
logger.log(Level.INFO, "No configuration for Scripts found, generating defaults..."); logger.log(Level.INFO, "No configuration for Scripts found, generating defaults...");
ModuleSettings.setConfigSetting(KeywordSearchSettings.PROPERTIES_SCRIPTS, SCRIPT.LATIN_1.name(), Boolean.toString(true)); ModuleSettings.setConfigSetting(KeywordSearchSettings.PROPERTIES_SCRIPTS, SCRIPT.LATIN_1.name(),
Boolean.toString(true));
} }
} }
} }

View File

@ -21,8 +21,11 @@ package org.sleuthkit.autopsy.keywordsearch;
import java.awt.Component; import java.awt.Component;
import java.io.File; import java.io.File;
import java.util.logging.Level; import java.util.logging.Level;
import org.sleuthkit.autopsy.coreutils.Logger; import org.sleuthkit.autopsy.coreutils.Logger;
import javax.swing.JOptionPane; import javax.swing.JOptionPane;
import org.sleuthkit.datamodel.AbstractFile; import org.sleuthkit.datamodel.AbstractFile;
import org.sleuthkit.datamodel.FsContent; import org.sleuthkit.datamodel.FsContent;
import org.sleuthkit.datamodel.TskException; import org.sleuthkit.datamodel.TskException;
@ -32,9 +35,10 @@ class KeywordSearchUtil {
public enum DIALOG_MESSAGE_TYPE { public enum DIALOG_MESSAGE_TYPE {
ERROR, WARN, INFO ERROR, WARN, INFO
}; }
private static final Logger logger = Logger.getLogger(KeywordSearchUtil.class.getName());
;
private static final Logger logger = Logger.getLogger(KeywordSearchUtil.class.getName());
/** /**
@ -117,7 +121,8 @@ class KeywordSearchUtil {
messageType); messageType);
} }
public static boolean displayConfirmDialog(final String title, final String message, final DIALOG_MESSAGE_TYPE type) { public static boolean displayConfirmDialog(final String title, final String message,
final DIALOG_MESSAGE_TYPE type) {
int messageType; int messageType;
if (type == DIALOG_MESSAGE_TYPE.ERROR) { if (type == DIALOG_MESSAGE_TYPE.ERROR) {
messageType = JOptionPane.ERROR_MESSAGE; messageType = JOptionPane.ERROR_MESSAGE;
@ -126,7 +131,8 @@ class KeywordSearchUtil {
} else { } else {
messageType = JOptionPane.INFORMATION_MESSAGE; messageType = JOptionPane.INFORMATION_MESSAGE;
} }
if (JOptionPane.showConfirmDialog(null, message, title, JOptionPane.YES_NO_OPTION, messageType) == JOptionPane.YES_OPTION) { if (JOptionPane.showConfirmDialog(null, message, title, JOptionPane.YES_NO_OPTION, messageType)
== JOptionPane.YES_OPTION) {
return true; return true;
} else { } else {
return false; return false;

View File

@ -21,6 +21,7 @@ package org.sleuthkit.autopsy.keywordsearch;
import java.util.Collection; import java.util.Collection;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map; import java.util.Map;
import org.sleuthkit.datamodel.BlackboardArtifact; import org.sleuthkit.datamodel.BlackboardArtifact;
import org.sleuthkit.datamodel.BlackboardAttribute; import org.sleuthkit.datamodel.BlackboardAttribute;

View File

@ -3,7 +3,7 @@
This file describes the schema definition for its twin files, which are loaded at runtime as notable keyword files. This file describes the schema definition for its twin files, which are loaded at runtime as notable keyword files.
--> -->
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"> <xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
<!-- definition of simple elements --> <!-- definition of simple elements -->
<xs:attribute name="name" type="xs:string"/> <xs:attribute name="name" type="xs:string"/>
<xs:attribute name="literal" type="xs:boolean"/> <xs:attribute name="literal" type="xs:boolean"/>
@ -11,7 +11,7 @@ This file describes the schema definition for its twin files, which are loaded a
<xs:attribute name="use_for_ingest" type="xs:boolean"/> <xs:attribute name="use_for_ingest" type="xs:boolean"/>
<xs:attribute name="key" type="xs:string"/> <xs:attribute name="key" type="xs:string"/>
<xs:attribute name="created" > <xs:attribute name="created">
<xs:simpleType> <xs:simpleType>
<xs:restriction base="xs:string"> <xs:restriction base="xs:string">
<xs:whiteSpace value="preserve"/> <xs:whiteSpace value="preserve"/>
@ -42,11 +42,11 @@ This file describes the schema definition for its twin files, which are loaded a
<xs:sequence> <xs:sequence>
<xs:element ref="keyword" minOccurs="0" maxOccurs="unbounded"/> <xs:element ref="keyword" minOccurs="0" maxOccurs="unbounded"/>
</xs:sequence> </xs:sequence>
<xs:attribute ref="created" use="required"/> <xs:attribute ref="created" use="required"/>
<xs:attribute ref="ingest_messages" default="true" use="optional"/> <xs:attribute ref="ingest_messages" default="true" use="optional"/>
<xs:attribute ref="modified" use="optional"/> <xs:attribute ref="modified" use="optional"/>
<xs:attribute ref="name" use="required"/> <xs:attribute ref="name" use="required"/>
<xs:attribute ref="use_for_ingest" default="true" use="optional"/> <xs:attribute ref="use_for_ingest" default="true" use="optional"/>
</xs:complexType> </xs:complexType>
</xs:element> </xs:element>

View File

@ -24,6 +24,7 @@ import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.logging.Level; import java.util.logging.Level;
import org.sleuthkit.autopsy.coreutils.Logger; import org.sleuthkit.autopsy.coreutils.Logger;
import org.apache.solr.client.solrj.SolrQuery; import org.apache.solr.client.solrj.SolrQuery;
import org.apache.solr.client.solrj.SolrRequest.METHOD; import org.apache.solr.client.solrj.SolrRequest.METHOD;
@ -44,7 +45,7 @@ import org.sleuthkit.datamodel.TskException;
/** /**
* Performs a normal string (i.e. non-regexp) query to SOLR/Lucene. * Performs a normal string (i.e. non-regexp) query to SOLR/Lucene.
* By default, matches in all fields. * By default, matches in all fields.
*/ */
class LuceneQuery implements KeywordSearchQuery { class LuceneQuery implements KeywordSearchQuery {
@ -53,7 +54,7 @@ class LuceneQuery implements KeywordSearchQuery {
private String keywordStringEscaped; private String keywordStringEscaped;
private boolean isEscaped; private boolean isEscaped;
private Keyword keywordQuery = null; private Keyword keywordQuery = null;
private final List <KeywordQueryFilter> filters = new ArrayList<KeywordQueryFilter>(); private final List<KeywordQueryFilter> filters = new ArrayList<KeywordQueryFilter>();
private String field = null; private String field = null;
private static final int MAX_RESULTS = 20000; private static final int MAX_RESULTS = 20000;
static final int SNIPPET_LENGTH = 50; static final int SNIPPET_LENGTH = 50;
@ -62,12 +63,13 @@ class LuceneQuery implements KeywordSearchQuery {
static final String HIGHLIGHT_FIELD_REGEX = Server.Schema.CONTENT.toString(); static final String HIGHLIGHT_FIELD_REGEX = Server.Schema.CONTENT.toString();
//TODO use content_ws stored="true" in solr schema for perfect highlight hits //TODO use content_ws stored="true" in solr schema for perfect highlight hits
//static final String HIGHLIGHT_FIELD_REGEX = Server.Schema.CONTENT_WS.toString() //static final String HIGHLIGHT_FIELD_REGEX = Server.Schema.CONTENT_WS.toString()
private static final boolean DEBUG = (Version.getBuildType() == Version.Type.DEVELOPMENT); private static final boolean DEBUG = (Version.getBuildType() == Version.Type.DEVELOPMENT);
/** /**
* Constructor with query to process. * Constructor with query to process.
* @param keywordQuery *
* @param keywordQuery
*/ */
public LuceneQuery(Keyword keywordQuery) { public LuceneQuery(Keyword keywordQuery) {
this(keywordQuery.getQuery()); this(keywordQuery.getQuery());
@ -76,6 +78,7 @@ class LuceneQuery implements KeywordSearchQuery {
/** /**
* Constructor with keyword string to process * Constructor with keyword string to process
*
* @param queryStr Keyword to search for * @param queryStr Keyword to search for
*/ */
public LuceneQuery(String queryStr) { public LuceneQuery(String queryStr) {
@ -88,7 +91,7 @@ class LuceneQuery implements KeywordSearchQuery {
public void addFilter(KeywordQueryFilter filter) { public void addFilter(KeywordQueryFilter filter) {
this.filters.add(filter); this.filters.add(filter);
} }
@Override @Override
public void setField(String field) { public void setField(String field) {
this.field = field; this.field = field;
@ -141,7 +144,8 @@ class LuceneQuery implements KeywordSearchQuery {
} }
@Override @Override
public KeywordWriteResult writeToBlackBoard(String termHit, AbstractFile newFsHit, String snippet, String listName) { public KeywordWriteResult writeToBlackBoard(String termHit, AbstractFile newFsHit, String snippet,
String listName) {
final String MODULE_NAME = KeywordSearchIngestModule.MODULE_NAME; final String MODULE_NAME = KeywordSearchIngestModule.MODULE_NAME;
KeywordWriteResult writeResult = null; KeywordWriteResult writeResult = null;
@ -156,7 +160,8 @@ class LuceneQuery implements KeywordSearchQuery {
} }
if (snippet != null) { if (snippet != null) {
attributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_KEYWORD_PREVIEW.getTypeID(), MODULE_NAME, snippet)); attributes
.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_KEYWORD_PREVIEW.getTypeID(), MODULE_NAME, snippet));
} }
//keyword //keyword
attributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_KEYWORD.getTypeID(), MODULE_NAME, termHit)); attributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_KEYWORD.getTypeID(), MODULE_NAME, termHit));
@ -186,9 +191,10 @@ class LuceneQuery implements KeywordSearchQuery {
return null; return null;
} }
/** /**
* Perform the query and return result * Perform the query and return result
*
* @return list of ContentHit objects * @return list of ContentHit objects
* @throws NoOpenCoreException * @throws NoOpenCoreException
*/ */
@ -212,7 +218,7 @@ class LuceneQuery implements KeywordSearchQuery {
sb.append(field).append(":").append(groupedQuery); sb.append(field).append(":").append(groupedQuery);
theQueryStr = sb.toString(); theQueryStr = sb.toString();
} }
q.setQuery(theQueryStr); q.setQuery(theQueryStr);
q.setRows(MAX_RESULTS); q.setRows(MAX_RESULTS);
q.setFields(Server.Schema.ID.toString()); q.setFields(Server.Schema.ID.toString());
@ -286,26 +292,30 @@ class LuceneQuery implements KeywordSearchQuery {
/** /**
* return snippet preview context * return snippet preview context
* @param query the keyword query for text to highlight. Lucene special cahrs should already be escaped. *
* @param query the keyword query for text to highlight. Lucene special cahrs should already be escaped.
* @param contentID content id associated with the file * @param contentID content id associated with the file
* @param isRegex whether the query is a regular expression (different Solr fields are then used to generate the preview) * @param isRegex whether the query is a regular expression (different Solr fields are then used to generate the preview)
* @param group whether the query should look for all terms grouped together in the query order, or not * @param group whether the query should look for all terms grouped together in the query order, or not
* @return * @return
*/ */
public static String querySnippet(String query, long contentID, boolean isRegex, boolean group) throws NoOpenCoreException { public static String querySnippet(String query, long contentID, boolean isRegex, boolean group)
throws NoOpenCoreException {
return querySnippet(query, contentID, 0, isRegex, group); return querySnippet(query, contentID, 0, isRegex, group);
} }
/** /**
* return snippet preview context * return snippet preview context
* @param query the keyword query for text to highlight. Lucene special cahrs should already be escaped. *
* @param query the keyword query for text to highlight. Lucene special cahrs should already be escaped.
* @param contentID content id associated with the hit * @param contentID content id associated with the hit
* @param chunkID chunk id associated with the content hit, or 0 if no chunks * @param chunkID chunk id associated with the content hit, or 0 if no chunks
* @param isRegex whether the query is a regular expression (different Solr fields are then used to generate the preview) * @param isRegex whether the query is a regular expression (different Solr fields are then used to generate the preview)
* @param group whether the query should look for all terms grouped together in the query order, or not * @param group whether the query should look for all terms grouped together in the query order, or not
* @return * @return
*/ */
public static String querySnippet(String query, long contentID, int chunkID, boolean isRegex, boolean group) throws NoOpenCoreException { public static String querySnippet(String query, long contentID, int chunkID, boolean isRegex, boolean group)
throws NoOpenCoreException {
Server solrServer = KeywordSearch.getServer(); Server solrServer = KeywordSearch.getServer();
String highlightField = null; String highlightField = null;
@ -318,7 +328,7 @@ class LuceneQuery implements KeywordSearchQuery {
SolrQuery q = new SolrQuery(); SolrQuery q = new SolrQuery();
String queryStr = null; String queryStr = null;
if (isRegex) { if (isRegex) {
StringBuilder sb = new StringBuilder(); StringBuilder sb = new StringBuilder();
sb.append(highlightField).append(":"); sb.append(highlightField).append(":");
@ -336,7 +346,7 @@ class LuceneQuery implements KeywordSearchQuery {
//always force grouping/quotes //always force grouping/quotes
queryStr = KeywordSearchUtil.quoteQuery(query); queryStr = KeywordSearchUtil.quoteQuery(query);
} }
q.setQuery(queryStr); q.setQuery(queryStr);
String contentIDStr = null; String contentIDStr = null;
@ -355,21 +365,20 @@ class LuceneQuery implements KeywordSearchQuery {
//q.setHighlightSimplePost("&raquo;"); //original highlighter only //q.setHighlightSimplePost("&raquo;"); //original highlighter only
q.setHighlightSnippets(1); q.setHighlightSnippets(1);
q.setHighlightFragsize(SNIPPET_LENGTH); q.setHighlightFragsize(SNIPPET_LENGTH);
//tune the highlighter //tune the highlighter
q.setParam("hl.useFastVectorHighlighter", "on"); //fast highlighter scales better than standard one q.setParam("hl.useFastVectorHighlighter", "on"); //fast highlighter scales better than standard one
q.setParam("hl.tag.pre", "&laquo;"); //makes sense for FastVectorHighlighter only q.setParam("hl.tag.pre", "&laquo;"); //makes sense for FastVectorHighlighter only
q.setParam("hl.tag.post", "&laquo;"); //makes sense for FastVectorHighlighter only q.setParam("hl.tag.post", "&laquo;"); //makes sense for FastVectorHighlighter only
q.setParam("hl.fragListBuilder", "simple"); //makes sense for FastVectorHighlighter only q.setParam("hl.fragListBuilder", "simple"); //makes sense for FastVectorHighlighter only
//Solr bug if fragCharSize is smaller than Query string, StringIndexOutOfBoundsException is thrown. //Solr bug if fragCharSize is smaller than Query string, StringIndexOutOfBoundsException is thrown.
q.setParam("hl.fragCharSize", Integer.toString(queryStr.length())); //makes sense for FastVectorHighlighter only q.setParam("hl.fragCharSize", Integer.toString(queryStr.length())); //makes sense for FastVectorHighlighter only
//docs says makes sense for the original Highlighter only, but not really //docs says makes sense for the original Highlighter only, but not really
//analyze all content SLOW! consider lowering //analyze all content SLOW! consider lowering
q.setParam("hl.maxAnalyzedChars", Server.HL_ANALYZE_CHARS_UNLIMITED); q.setParam("hl.maxAnalyzedChars", Server.HL_ANALYZE_CHARS_UNLIMITED);
try { try {
QueryResponse response = solrServer.query(q, METHOD.POST); QueryResponse response = solrServer.query(q, METHOD.POST);

View File

@ -22,34 +22,34 @@ import java.util.LinkedHashMap;
/** /**
* Interface to provide HTML text to display in ExtractedContentViewer. * Interface to provide HTML text to display in ExtractedContentViewer.
* There is a SOLR implementaiton of this that interfaces with SOLR to * There is a SOLR implementaiton of this that interfaces with SOLR to
* highlight the keyword hits and a version that does not do markup * highlight the keyword hits and a version that does not do markup
* so that you can simply view the stored text. * so that you can simply view the stored text.
*/ */
interface MarkupSource { interface MarkupSource {
/** /**
* @return text optionally marked up with the subsest of HTML that Swing * @return text optionally marked up with the subsest of HTML that Swing
* components can handle in their setText() method. * components can handle in their setText() method.
*
*/ */
String getMarkup(); String getMarkup();
/** /**
*
* @return true if markup is marked to be searchable * @return true if markup is marked to be searchable
*/ */
boolean isSearchable(); boolean isSearchable();
/** /**
* If searchable markup, returns prefix of anchor, otherwise return empty string * If searchable markup, returns prefix of anchor, otherwise return empty string
* @return *
* @return
*/ */
String getAnchorPrefix(); String getAnchorPrefix();
/** /**
* if searchable markup, returns number of hits found and encoded in the markup * if searchable markup, returns number of hits found and encoded in the markup
* @return *
* @return
*/ */
int getNumberHits(); int getNumberHits();
@ -58,80 +58,92 @@ interface MarkupSource {
*/ */
@Override @Override
String toString(); String toString();
/** /**
* get number pages/chunks * get number pages/chunks
*
* @return number pages * @return number pages
*/ */
int getNumberPages(); int getNumberPages();
/** /**
* get the current page number * get the current page number
*
* @return current page number * @return current page number
*/ */
int getCurrentPage(); int getCurrentPage();
/** /**
* Check if has next page * Check if has next page
*
* @return true, if next page exists in the source * @return true, if next page exists in the source
*/ */
boolean hasNextPage(); boolean hasNextPage();
/** /**
* Move to next page * Move to next page
*
* @return the new page number * @return the new page number
*/ */
int nextPage(); int nextPage();
/** /**
* Check if has previous page * Check if has previous page
*
* @return true, if previous page exists in the source * @return true, if previous page exists in the source
*/ */
boolean hasPreviousPage(); boolean hasPreviousPage();
/** /**
* Move to previous page * Move to previous page
*
* @return the new page number * @return the new page number
*/ */
int previousPage(); int previousPage();
/** /**
* Check if has next searchable item * Check if has next searchable item
*
* @return true, if next item exists in the source * @return true, if next item exists in the source
*/ */
boolean hasNextItem(); boolean hasNextItem();
/** /**
* Move to next item * Move to next item
*
* @return the new item number * @return the new item number
*/ */
int nextItem(); int nextItem();
/** /**
* Check if has previous item * Check if has previous item
*
* @return true, if previous item exists in the source * @return true, if previous item exists in the source
*/ */
boolean hasPreviousItem(); boolean hasPreviousItem();
/** /**
* Move to previous item * Move to previous item
*
* @return the new item number * @return the new item number
*/ */
int previousItem(); int previousItem();
/** /**
* Get the current item number, do not change anything * Get the current item number, do not change anything
*
* @return the current item number * @return the current item number
*/ */
int currentItem(); int currentItem();
/** /**
* get a map storing which pages have matches to their number, or 0 if unknown * get a map storing which pages have matches to their number, or 0 if unknown
*
* @return map storing pages with matches, or null if not supported * @return map storing pages with matches, or null if not supported
*/ */
LinkedHashMap<Integer,Integer> getHitsPages(); LinkedHashMap<Integer, Integer> getHitsPages();
} }

View File

@ -19,7 +19,6 @@
package org.sleuthkit.autopsy.keywordsearch; package org.sleuthkit.autopsy.keywordsearch;
/** /**
*
* Exception thrown when no core is open * Exception thrown when no core is open
*/ */
class NoOpenCoreException extends Exception { class NoOpenCoreException extends Exception {
@ -28,5 +27,5 @@ class NoOpenCoreException extends Exception {
super("No currently open Solr core."); super("No currently open Solr core.");
} }
} }

View File

@ -41,8 +41,11 @@ import java.util.ArrayList;
import java.util.Collections; import java.util.Collections;
import java.util.List; import java.util.List;
import java.util.logging.Level; import java.util.logging.Level;
import org.sleuthkit.autopsy.coreutils.Logger; import org.sleuthkit.autopsy.coreutils.Logger;
import javax.swing.AbstractAction; import javax.swing.AbstractAction;
import org.apache.solr.client.solrj.SolrQuery; import org.apache.solr.client.solrj.SolrQuery;
import org.apache.solr.client.solrj.SolrServer; import org.apache.solr.client.solrj.SolrServer;
import org.apache.solr.client.solrj.SolrServerException; import org.apache.solr.client.solrj.SolrServerException;
@ -133,8 +136,11 @@ class Server {
return "num_chunks"; return "num_chunks";
} }
}, },
}; }
public static final String HL_ANALYZE_CHARS_UNLIMITED = "500000"; //max 1MB in a chunk. use -1 for unlimited, but -1 option may not be supported (not documented)
;
public static final String HL_ANALYZE_CHARS_UNLIMITED = "500000";
//max 1MB in a chunk. use -1 for unlimited, but -1 option may not be supported (not documented)
//max content size we can send to Solr //max content size we can send to Solr
public static final long MAX_CONTENT_SIZE = 1L * 1024 * 1024 * 1024; public static final long MAX_CONTENT_SIZE = 1L * 1024 * 1024 * 1024;
private static final Logger logger = Logger.getLogger(Server.class.getName()); private static final Logger logger = Logger.getLogger(Server.class.getName());
@ -143,7 +149,8 @@ class Server {
public static final String CORE_EVT = "CORE_EVT"; public static final String CORE_EVT = "CORE_EVT";
public static final char ID_CHUNK_SEP = '_'; public static final char ID_CHUNK_SEP = '_';
private String javaPath = "java"; private String javaPath = "java";
public static final Charset DEFAULT_INDEXED_TEXT_CHARSET = Charset.forName("UTF-8"); ///< default Charset to index text as public static final Charset DEFAULT_INDEXED_TEXT_CHARSET = Charset.forName("UTF-8");
///< default Charset to index text as
private static final int MAX_SOLR_MEM_MB = 512; //TODO set dynamically based on avail. system resources private static final int MAX_SOLR_MEM_MB = 512; //TODO set dynamically based on avail. system resources
private Process curSolrProcess = null; private Process curSolrProcess = null;
private static Ingester ingester = null; private static Ingester ingester = null;
@ -160,7 +167,9 @@ class Server {
public enum CORE_EVT_STATES { public enum CORE_EVT_STATES {
STOPPED, STARTED STOPPED, STARTED
}; }
;
private SolrServer solrServer; private SolrServer solrServer;
private String instanceDir; private String instanceDir;
private File solrFolder; private File solrFolder;
@ -189,26 +198,34 @@ class Server {
private void initSettings() { private void initSettings() {
if (ModuleSettings.settingExists(PROPERTIES_FILE, PROPERTIES_CURRENT_SERVER_PORT)) { if (ModuleSettings.settingExists(PROPERTIES_FILE, PROPERTIES_CURRENT_SERVER_PORT)) {
try { try {
currentSolrServerPort = Integer.decode(ModuleSettings.getConfigSetting(PROPERTIES_FILE, PROPERTIES_CURRENT_SERVER_PORT)); currentSolrServerPort = Integer
.decode(ModuleSettings.getConfigSetting(PROPERTIES_FILE, PROPERTIES_CURRENT_SERVER_PORT));
} catch (NumberFormatException nfe) { } catch (NumberFormatException nfe) {
logger.log(Level.WARNING, "Could not decode indexing server port, value was not a valid port number, using the default. ", nfe); logger.log(Level.WARNING,
"Could not decode indexing server port, value was not a valid port number, using the default. ",
nfe);
currentSolrServerPort = DEFAULT_SOLR_SERVER_PORT; currentSolrServerPort = DEFAULT_SOLR_SERVER_PORT;
} }
} else { } else {
currentSolrServerPort = DEFAULT_SOLR_SERVER_PORT; currentSolrServerPort = DEFAULT_SOLR_SERVER_PORT;
ModuleSettings.setConfigSetting(PROPERTIES_FILE, PROPERTIES_CURRENT_SERVER_PORT, String.valueOf(currentSolrServerPort)); ModuleSettings.setConfigSetting(PROPERTIES_FILE, PROPERTIES_CURRENT_SERVER_PORT,
String.valueOf(currentSolrServerPort));
} }
if (ModuleSettings.settingExists(PROPERTIES_FILE, PROPERTIES_CURRENT_STOP_PORT)) { if (ModuleSettings.settingExists(PROPERTIES_FILE, PROPERTIES_CURRENT_STOP_PORT)) {
try { try {
currentSolrStopPort = Integer.decode(ModuleSettings.getConfigSetting(PROPERTIES_FILE, PROPERTIES_CURRENT_STOP_PORT)); currentSolrStopPort = Integer
.decode(ModuleSettings.getConfigSetting(PROPERTIES_FILE, PROPERTIES_CURRENT_STOP_PORT));
} catch (NumberFormatException nfe) { } catch (NumberFormatException nfe) {
logger.log(Level.WARNING, "Could not decode indexing server stop port, value was not a valid port number, using default", nfe); logger.log(Level.WARNING,
"Could not decode indexing server stop port, value was not a valid port number, using default",
nfe);
currentSolrStopPort = DEFAULT_SOLR_STOP_PORT; currentSolrStopPort = DEFAULT_SOLR_STOP_PORT;
} }
} else { } else {
currentSolrStopPort = DEFAULT_SOLR_STOP_PORT; currentSolrStopPort = DEFAULT_SOLR_STOP_PORT;
ModuleSettings.setConfigSetting(PROPERTIES_FILE, PROPERTIES_CURRENT_STOP_PORT, String.valueOf(currentSolrStopPort)); ModuleSettings.setConfigSetting(PROPERTIES_FILE, PROPERTIES_CURRENT_STOP_PORT,
String.valueOf(currentSolrStopPort));
} }
} }
@ -299,7 +316,7 @@ class Server {
logger.log(Level.WARNING, "Error closing Solr output stream writer"); logger.log(Level.WARNING, "Error closing Solr output stream writer");
} }
} }
if (br != null) { if (br != null) {
try { try {
br.close(); br.close();
} catch (IOException ex) { } catch (IOException ex) {
@ -366,21 +383,21 @@ class Server {
final String loggingProperties = loggingPropertiesOpt + loggingPropertiesFilePath; final String loggingProperties = loggingPropertiesOpt + loggingPropertiesFilePath;
final String [] SOLR_START_CMD = { final String[] SOLR_START_CMD = {
javaPath, javaPath,
MAX_SOLR_MEM_MB_PAR, MAX_SOLR_MEM_MB_PAR,
"-DSTOP.PORT=" + currentSolrStopPort, "-DSTOP.PORT=" + currentSolrStopPort,
"-Djetty.port=" + currentSolrServerPort, "-Djetty.port=" + currentSolrServerPort,
"-DSTOP.KEY=" + KEY, "-DSTOP.KEY=" + KEY,
loggingProperties, loggingProperties,
"-jar", "-jar",
"start.jar"}; "start.jar"};
StringBuilder cmdSb = new StringBuilder(); StringBuilder cmdSb = new StringBuilder();
for (int i = 0; i<SOLR_START_CMD.length; ++i ) { for (int i = 0; i < SOLR_START_CMD.length; ++i) {
cmdSb.append(SOLR_START_CMD[i]).append(" "); cmdSb.append(SOLR_START_CMD[i]).append(" ");
} }
logger.log(Level.INFO, "Starting Solr using: " + cmdSb.toString()); logger.log(Level.INFO, "Starting Solr using: " + cmdSb.toString());
curSolrProcess = Runtime.getRuntime().exec(SOLR_START_CMD, null, solrFolder); curSolrProcess = Runtime.getRuntime().exec(SOLR_START_CMD, null, solrFolder);
logger.log(Level.INFO, "Finished starting Solr"); logger.log(Level.INFO, "Finished starting Solr");
@ -409,7 +426,8 @@ class Server {
throw new KeywordSearchModuleException("Could not start Solr server process", ex); throw new KeywordSearchModuleException("Could not start Solr server process", ex);
} }
} else { } else {
logger.log(Level.WARNING, "Could not start Solr server process, port [" + currentSolrServerPort + "] not available!"); logger.log(Level.WARNING,
"Could not start Solr server process, port [" + currentSolrServerPort + "] not available!");
throw new SolrServerNoPortException(currentSolrServerPort); throw new SolrServerNoPortException(currentSolrServerPort);
} }
} }
@ -465,20 +483,20 @@ class Server {
/** /**
* Tries to stop a Solr instance. * Tries to stop a Solr instance.
* * <p/>
* Waits for the stop command to finish before returning. * Waits for the stop command to finish before returning.
*/ */
synchronized void stop() { synchronized void stop() {
try { try {
logger.log(Level.INFO, "Stopping Solr server from: " + solrFolder.getAbsolutePath()); logger.log(Level.INFO, "Stopping Solr server from: " + solrFolder.getAbsolutePath());
//try graceful shutdown //try graceful shutdown
final String [] SOLR_STOP_CMD = { final String[] SOLR_STOP_CMD = {
javaPath, javaPath,
"-DSTOP.PORT=" + currentSolrStopPort, "-DSTOP.PORT=" + currentSolrStopPort,
"-DSTOP.KEY=" + KEY, "-DSTOP.KEY=" + KEY,
"-jar", "-jar",
"start.jar", "start.jar",
"--stop", "--stop",
}; };
Process stop = Runtime.getRuntime().exec(SOLR_STOP_CMD, null, solrFolder); Process stop = Runtime.getRuntime().exec(SOLR_STOP_CMD, null, solrFolder);
logger.log(Level.INFO, "Waiting for stopping Solr server"); logger.log(Level.INFO, "Waiting for stopping Solr server");
@ -532,7 +550,8 @@ class Server {
// TODO: check if SocketExceptions should actually happen (is // TODO: check if SocketExceptions should actually happen (is
// probably caused by starting a connection as the server finishes // probably caused by starting a connection as the server finishes
// shutting down) // shutting down)
if (cause instanceof ConnectException || cause instanceof SocketException) { //|| cause instanceof NoHttpResponseException) { if (cause instanceof ConnectException
|| cause instanceof SocketException) { //|| cause instanceof NoHttpResponseException) {
logger.log(Level.INFO, "Solr server is not running, cause: " + cause.getMessage()); logger.log(Level.INFO, "Solr server is not running, cause: " + cause.getMessage());
return false; return false;
} else { } else {
@ -544,6 +563,7 @@ class Server {
return true; return true;
} }
/** /**
* ** Convenience methods for use while we only open one case at a time *** * ** Convenience methods for use while we only open one case at a time ***
*/ */
@ -769,13 +789,14 @@ class Server {
/** /**
* Execute solr query * Execute solr query
* *
* @param sq the query * @param sq the query
* @param method http method to use * @param method http method to use
* @return query response * @return query response
* @throws KeywordSearchModuleException * @throws KeywordSearchModuleException
* @throws NoOpenCoreException * @throws NoOpenCoreException
*/ */
public QueryResponse query(SolrQuery sq, SolrRequest.METHOD method) throws KeywordSearchModuleException, NoOpenCoreException { public QueryResponse query(SolrQuery sq, SolrRequest.METHOD method)
throws KeywordSearchModuleException, NoOpenCoreException {
if (currentCore == null) { if (currentCore == null) {
throw new NoOpenCoreException(); throw new NoOpenCoreException();
} }
@ -824,7 +845,7 @@ class Server {
* *
* @param content to get the text for * @param content to get the text for
* @param chunkID chunk number to query (starting at 1), or 0 if there is no * @param chunkID chunk number to query (starting at 1), or 0 if there is no
* chunks for that content * chunks for that content
* @return content text string or null if error quering * @return content text string or null if error quering
* @throws NoOpenCoreException * @throws NoOpenCoreException
*/ */
@ -849,7 +870,7 @@ class Server {
* chunk as stored in Solr, e.g. FILEID_CHUNKID * chunk as stored in Solr, e.g. FILEID_CHUNKID
* *
* @param parentID the parent file id (id of the source content) * @param parentID the parent file id (id of the source content)
* @param childID the child chunk id * @param childID the child chunk id
* @return formatted string id * @return formatted string id
*/ */
public static String getChunkIdString(long parentID, int childID) { public static String getChunkIdString(long parentID, int childID) {
@ -860,7 +881,7 @@ class Server {
* Open a new core * Open a new core
* *
* @param coreName name to refer to the core by in Solr * @param coreName name to refer to the core by in Solr
* @param dataDir directory to load/store the core data from/to * @param dataDir directory to load/store the core data from/to
* @return new core * @return new core
*/ */
private Core openCore(String coreName, File dataDir) throws KeywordSearchModuleException { private Core openCore(String coreName, File dataDir) throws KeywordSearchModuleException {
@ -958,19 +979,24 @@ class Server {
try { try {
solrCore.add(doc); solrCore.add(doc);
} catch (SolrServerException ex) { } catch (SolrServerException ex) {
logger.log(Level.SEVERE, "Could not add document to index via update handler: " + doc.getField("id"), ex); logger.log(Level.SEVERE, "Could not add document to index via update handler: " + doc.getField("id"),
throw new KeywordSearchModuleException("Could not add document to index via update handler: " + doc.getField("id"), ex); ex);
throw new KeywordSearchModuleException(
"Could not add document to index via update handler: " + doc.getField("id"), ex);
} catch (IOException ex) { } catch (IOException ex) {
logger.log(Level.SEVERE, "Could not add document to index via update handler: " + doc.getField("id"), ex); logger.log(Level.SEVERE, "Could not add document to index via update handler: " + doc.getField("id"),
throw new KeywordSearchModuleException("Could not add document to index via update handler: " + doc.getField("id"), ex); ex);
throw new KeywordSearchModuleException(
"Could not add document to index via update handler: " + doc.getField("id"), ex);
} }
} }
/** /**
* get the text from the content field for the given file * get the text from the content field for the given file
*
* @param contentID * @param contentID
* @param chunkID * @param chunkID
* @return * @return
*/ */
private String getSolrContent(long contentID, int chunkID) { private String getSolrContent(long contentID, int chunkID) {
final SolrQuery q = new SolrQuery(); final SolrQuery q = new SolrQuery();
@ -1059,7 +1085,7 @@ class Server {
* Execute query that gets number of indexed file chunks for a file * Execute query that gets number of indexed file chunks for a file
* *
* @param contentID file id of the original file broken into chunks and * @param contentID file id of the original file broken into chunks and
* indexed * indexed
* @return int representing number of indexed file chunks, 0 if there is * @return int representing number of indexed file chunks, 0 if there is
* no chunks * no chunks
* @throws SolrServerException * @throws SolrServerException
@ -1092,8 +1118,8 @@ class Server {
SolrServerNoPortException(int port) { SolrServerNoPortException(int port) {
super("Indexing server could not bind to port " + port super("Indexing server could not bind to port " + port
+ ", port is not available, consider change the default " + ", port is not available, consider change the default "
+ Server.PROPERTIES_CURRENT_SERVER_PORT + " port."); + Server.PROPERTIES_CURRENT_SERVER_PORT + " port.");
this.port = port; this.port = port;
} }

View File

@ -26,9 +26,12 @@ import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Set; import java.util.Set;
import java.util.logging.Level; import java.util.logging.Level;
import org.sleuthkit.autopsy.coreutils.Logger; import org.sleuthkit.autopsy.coreutils.Logger;
import java.util.regex.Pattern; import java.util.regex.Pattern;
import java.util.regex.PatternSyntaxException; import java.util.regex.PatternSyntaxException;
import org.apache.solr.client.solrj.SolrQuery; import org.apache.solr.client.solrj.SolrQuery;
import org.apache.solr.client.solrj.SolrServerException; import org.apache.solr.client.solrj.SolrServerException;
import org.apache.solr.client.solrj.response.TermsResponse; import org.apache.solr.client.solrj.response.TermsResponse;
@ -43,7 +46,7 @@ import org.sleuthkit.datamodel.TskException;
/** /**
* Performs a regular expression query to the SOLR/Lucene instance. * Performs a regular expression query to the SOLR/Lucene instance.
*/ */
class TermComponentQuery implements KeywordSearchQuery { class TermComponentQuery implements KeywordSearchQuery {
@ -61,7 +64,7 @@ class TermComponentQuery implements KeywordSearchQuery {
private final List<KeywordQueryFilter> filters = new ArrayList<KeywordQueryFilter>(); private final List<KeywordQueryFilter> filters = new ArrayList<KeywordQueryFilter>();
private String field = null; private String field = null;
private static int MAX_TERMS_RESULTS = 20000; private static int MAX_TERMS_RESULTS = 20000;
private static final boolean DEBUG = (Version.getBuildType() == Version.Type.DEVELOPMENT); private static final boolean DEBUG = (Version.getBuildType() == Version.Type.DEVELOPMENT);
public TermComponentQuery(Keyword keywordQuery) { public TermComponentQuery(Keyword keywordQuery) {
@ -167,7 +170,8 @@ class TermComponentQuery implements KeywordSearchQuery {
} }
@Override @Override
public KeywordWriteResult writeToBlackBoard(String termHit, AbstractFile newFsHit, String snippet, String listName) { public KeywordWriteResult writeToBlackBoard(String termHit, AbstractFile newFsHit, String snippet,
String listName) {
final String MODULE_NAME = KeywordSearchIngestModule.MODULE_NAME; final String MODULE_NAME = KeywordSearchIngestModule.MODULE_NAME;
//there is match actually in this file, create artifact only then //there is match actually in this file, create artifact only then
@ -193,7 +197,8 @@ class TermComponentQuery implements KeywordSearchQuery {
//preview //preview
if (snippet != null) { if (snippet != null) {
attributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_KEYWORD_PREVIEW.getTypeID(), MODULE_NAME, snippet)); attributes
.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_KEYWORD_PREVIEW.getTypeID(), MODULE_NAME, snippet));
} }
//regex keyword //regex keyword
attributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_KEYWORD_REGEXP.getTypeID(), MODULE_NAME, termsQuery)); attributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_KEYWORD_REGEXP.getTypeID(), MODULE_NAME, termsQuery));
@ -226,12 +231,12 @@ class TermComponentQuery implements KeywordSearchQuery {
final SolrQuery q = createQuery(); final SolrQuery q = createQuery();
q.setShowDebugInfo(DEBUG); q.setShowDebugInfo(DEBUG);
q.setTermsLimit(MAX_TERMS_RESULTS); q.setTermsLimit(MAX_TERMS_RESULTS);
logger.log(Level.INFO, "Query: " + q.toString()); logger.log(Level.INFO, "Query: " + q.toString());
terms = executeQuery(q); terms = executeQuery(q);
int resultSize = 0; int resultSize = 0;
for (Term term : terms) { for (Term term : terms) {
final String termStr = KeywordSearchUtil.escapeLuceneQuery(term.getTerm()); final String termStr = KeywordSearchUtil.escapeLuceneQuery(term.getTerm());
@ -260,7 +265,7 @@ class TermComponentQuery implements KeywordSearchQuery {
} }
} }
//TODO limit how many results we store, not to hit memory limits //TODO limit how many results we store, not to hit memory limits
logger.log(Level.INFO, "Regex # results: " + resultSize); logger.log(Level.INFO, "Regex # results: " + resultSize);

View File

@ -21,8 +21,8 @@ package org.sleuthkit.autopsy.keywordsearch;
import org.sleuthkit.datamodel.AbstractFile; import org.sleuthkit.datamodel.AbstractFile;
/** /**
* *
* *
*/ */
interface TextLanguageIdentifier { interface TextLanguageIdentifier {
@ -31,7 +31,7 @@ interface TextLanguageIdentifier {
* black board for the given {@code AbstractFile} as a TSK_TEXT_LANGUAGE * black board for the given {@code AbstractFile} as a TSK_TEXT_LANGUAGE
* attribute on a TSK_GEN_INFO artifact. * attribute on a TSK_GEN_INFO artifact.
* *
* @param extracted the String whose language is to be identified * @param extracted the String whose language is to be identified
* @param sourceFile the AbstractFile the string is extracted from. * @param sourceFile the AbstractFile the string is extracted from.
* @return * @return
*/ */

View File

@ -19,6 +19,7 @@
package org.sleuthkit.autopsy.keywordsearch; package org.sleuthkit.autopsy.keywordsearch;
import java.util.logging.Level; import java.util.logging.Level;
import org.sleuthkit.autopsy.coreutils.Logger; import org.sleuthkit.autopsy.coreutils.Logger;
import org.sleuthkit.datamodel.AbstractFile; import org.sleuthkit.datamodel.AbstractFile;
import org.sleuthkit.datamodel.BlackboardArtifact; import org.sleuthkit.datamodel.BlackboardArtifact;
@ -53,9 +54,11 @@ class TikaLanguageIdentifier implements TextLanguageIdentifier {
genInfo.addAttribute(textLang); genInfo.addAttribute(textLang);
} catch (TskCoreException ex) { } catch (TskCoreException ex) {
logger.log(Level.WARNING, "failed to add TSK_TEXT_LANGUAGE attribute to TSK_GEN_INFO artifact for file: " + sourceFile.getName(), ex); logger.log(Level.WARNING,
"failed to add TSK_TEXT_LANGUAGE attribute to TSK_GEN_INFO artifact for file: " + sourceFile
.getName(), ex);
} }
} }
} }
} }

View File

@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
@HelpSetRegistration(helpSet = "keywordsearch-hs.xml", position = 3521) @HelpSetRegistration(helpSet = "keywordsearch-hs.xml",
package org.sleuthkit.autopsy.keywordsearch.docs; position = 3521) package org.sleuthkit.autopsy.keywordsearch.docs;
import org.netbeans.api.javahelp.HelpSetRegistration; import org.netbeans.api.javahelp.HelpSetRegistration;

View File

@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE filesystem PUBLIC "-//NetBeans//DTD Filesystem 1.2//EN" "http://www.netbeans.org/dtds/filesystem-1_2.dtd"> <!DOCTYPE filesystem PUBLIC "-//NetBeans//DTD Filesystem 1.2//EN" "http://www.netbeans.org/dtds/filesystem-1_2.dtd">
<filesystem> <filesystem>
<!-- ====================================================== <!-- ======================================================
Actions Actions
====================================================== --> ====================================================== -->
@ -10,22 +10,24 @@
<file name="org-sleuthkit-autopsy-keywordsearch-KeywordSearchConfigurationAction.instance"/> <file name="org-sleuthkit-autopsy-keywordsearch-KeywordSearchConfigurationAction.instance"/>
<file name="org-sleuthkit-autopsy-keywordsearch-KeywordSearchAction.instance"> <file name="org-sleuthkit-autopsy-keywordsearch-KeywordSearchAction.instance">
<attr name="delegate" newvalue="org.sleuthkit.autopsy.keywordsearch.KeywordSearchAction"/> <attr name="delegate" newvalue="org.sleuthkit.autopsy.keywordsearch.KeywordSearchAction"/>
<attr name="displayName" bundlevalue="org.sleuthkit.autopsy.keywordsearch.Bundle#CTL_KeywordSearchAction"/> <attr name="displayName"
bundlevalue="org.sleuthkit.autopsy.keywordsearch.Bundle#CTL_KeywordSearchAction"/>
</file> </file>
</folder> </folder>
</folder> </folder>
<!-- ====================================================== <!-- ======================================================
Services Services
======================================================= --> ======================================================= -->
<folder name="Services"> <folder name="Services">
<file name="org-sleuthkit-autopsy-keywordsearch-HighlightedMatchesSource.instance"> <file name="org-sleuthkit-autopsy-keywordsearch-HighlightedMatchesSource.instance">
<attr name="instanceOf" stringvalue="org.sleuthkit.autopsy.datamodel.HighlightLookup"/> <attr name="instanceOf" stringvalue="org.sleuthkit.autopsy.datamodel.HighlightLookup"/>
<attr name="instanceCreate" methodvalue="org.sleuthkit.autopsy.keywordsearch.HighlightedMatchesSource.getDefault"/> <attr name="instanceCreate"
methodvalue="org.sleuthkit.autopsy.keywordsearch.HighlightedMatchesSource.getDefault"/>
<attr name="position" intvalue="250"/> <attr name="position" intvalue="250"/>
</file> </file>
</folder> </folder>
<!-- ====================================================== <!-- ======================================================
Toolbars Toolbars
====================================================== --> ====================================================== -->
@ -33,9 +35,10 @@
<folder name="Keyword"> <folder name="Keyword">
<attr name="position" intvalue="104"/> <attr name="position" intvalue="104"/>
<file name="org-sleuthkit-autopsy-keywordsearch-KeywordSearchAction.shadow"> <file name="org-sleuthkit-autopsy-keywordsearch-KeywordSearchAction.shadow">
<attr name="originalFile" stringvalue="Actions/Tools/org-sleuthkit-autopsy-keywordsearch-KeywordSearchAction.instance"/> <attr name="originalFile"
stringvalue="Actions/Tools/org-sleuthkit-autopsy-keywordsearch-KeywordSearchAction.instance"/>
</file> </file>
</folder> </folder>
</folder> </folder>
</filesystem> </filesystem>