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;
import java.nio.charset.Charset;
import org.sleuthkit.autopsy.keywordsearch.Ingester.IngesterException;
/**
@ -51,7 +52,8 @@ class AbstractFileChunk {
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;
ByteContentStream bcs = new ByteContentStream(content, contentSize, parent.getSourceFile(), indexCharset);
try {
@ -59,9 +61,11 @@ class AbstractFileChunk {
//logger.log(Level.INFO, "Ingesting string chunk: " + this.getName() + ": " + chunkID);
} catch (Exception ingEx) {
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;
}
}

View File

@ -21,6 +21,7 @@ package org.sleuthkit.autopsy.keywordsearch;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import org.sleuthkit.autopsy.coreutils.StringExtract.StringExtractUnicodeTable.SCRIPT;
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_UTF8, ///< extract UTF8 text, possible values Boolean.TRUE.toString(), Boolean.FALSE.toString()
};
}
;
//generally text extractors should ignore archives
//and let unpacking modules take case of them
static final List<String> ARCHIVE_MIME_TYPES =
Arrays.asList(
//ignore unstructured binary and compressed data, for which string extraction or unzipper works better
"application/x-7z-compressed",
"application/x-ace-compressed",
"application/x-alz-compressed",
"application/x-arj",
"application/vnd.ms-cab-compressed",
"application/x-cfs-compressed",
"application/x-dgc-compressed",
"application/x-apple-diskimage",
"application/x-gca-compressed",
"application/x-dar",
"application/x-lzx",
"application/x-lzh",
"application/x-rar-compressed",
"application/x-stuffit",
"application/x-stuffitx",
"application/x-gtar",
"application/x-archive",
"application/x-executable",
"application/x-gzip",
"application/zip",
"application/x-zoo",
"application/x-cpio",
"application/x-shar",
"application/x-tar",
"application/x-bzip",
"application/x-bzip2",
"application/x-lzip",
"application/x-lzma",
"application/x-lzop",
"application/x-z",
"application/x-compress");
//ignore unstructured binary and compressed data, for which string extraction or unzipper works better
"application/x-7z-compressed",
"application/x-ace-compressed",
"application/x-alz-compressed",
"application/x-arj",
"application/vnd.ms-cab-compressed",
"application/x-cfs-compressed",
"application/x-dgc-compressed",
"application/x-apple-diskimage",
"application/x-gca-compressed",
"application/x-dar",
"application/x-lzx",
"application/x-lzh",
"application/x-rar-compressed",
"application/x-stuffit",
"application/x-stuffitx",
"application/x-gtar",
"application/x-archive",
"application/x-executable",
"application/x-gzip",
"application/zip",
"application/x-zoo",
"application/x-cpio",
"application/x-shar",
"application/x-tar",
"application/x-bzip",
"application/x-bzip2",
"application/x-lzip",
"application/x-lzma",
"application/x-lzop",
"application/x-z",
"application/x-compress");
/**
* 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
* 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)
* or null if not detected
* or null if not detected
* @return true if the file content is supported, false otherwise
*/
boolean isSupported(AbstractFile file, String detectedFormat);

View File

@ -26,6 +26,7 @@ import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.logging.Level;
import org.sleuthkit.autopsy.coreutils.Logger;
import org.sleuthkit.autopsy.coreutils.StringExtract.StringExtractUnicodeTable.SCRIPT;
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,
* chunks are indexed with Solr.
*/
class AbstractFileHtmlExtract implements AbstractFileExtract {
class AbstractFileHtmlExtract implements AbstractFileExtract {
private static final Logger logger = Logger.getLogger(AbstractFileHtmlExtract.class.getName());
static final Charset outCharset = Server.DEFAULT_INDEXED_TEXT_CHARSET;
@ -58,7 +59,7 @@ import org.sleuthkit.datamodel.ReadContentInputStream;
"text/html",
"text/javascript" //"application/xml",
//"application/xml-dtd",
);
);
private final TikaLanguageIdentifier tikaLanguageIdentifier;
AbstractFileHtmlExtract() {
@ -189,10 +190,12 @@ import org.sleuthkit.datamodel.ReadContentInputStream;
module.checkRunCommitSearch();
}
} 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;
} 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;
} finally {
try {

View File

@ -23,6 +23,7 @@ import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.Reader;
import java.nio.charset.Charset;
import org.sleuthkit.autopsy.coreutils.Logger;
import org.apache.solr.common.util.ContentStream;
import org.sleuthkit.datamodel.AbstractContent;
@ -31,7 +32,7 @@ import org.sleuthkit.datamodel.AbstractFile;
/**
* Wrapper over InputStream that implements ContentStream to feed to Solr.
*/
class AbstractFileStringContentStream implements ContentStream {
class AbstractFileStringContentStream implements ContentStream {
//input
private AbstractFile content;
@ -69,7 +70,8 @@ import org.sleuthkit.datamodel.AbstractFile;
@Override
public Long getSize() {
//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
@ -85,7 +87,7 @@ import org.sleuthkit.datamodel.AbstractFile;
@Override
protected void finalize() throws Throwable {
super.finalize();
stream.close();
}
}

View File

@ -26,6 +26,7 @@ import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.logging.Level;
import org.sleuthkit.autopsy.coreutils.Logger;
import org.sleuthkit.autopsy.coreutils.StringExtract.StringExtractUnicodeTable.SCRIPT;
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 final List<SCRIPT> extractScripts = new ArrayList<SCRIPT>();
private Map<String, String> extractOptions = new HashMap<String, String>();
//disabled prepending of BOM
//static {
@ -132,7 +133,8 @@ class AbstractFileStringExtract implements AbstractFileExtract {
//break input stream into chunks
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));
//debug.write(STRING_CHUNK_BUF, 0, (int)readSize);
@ -143,7 +145,9 @@ class AbstractFileStringExtract implements AbstractFileExtract {
++this.numChunks;
} catch (IngesterException ingEx) {
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
}
@ -159,7 +163,8 @@ class AbstractFileStringExtract implements AbstractFileExtract {
ingester.ingest(this);
} 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;
} finally {
try {

View File

@ -22,6 +22,7 @@ import java.io.IOException;
import java.io.InputStream;
import java.nio.charset.Charset;
import java.util.List;
import org.sleuthkit.autopsy.coreutils.Logger;
import org.sleuthkit.autopsy.coreutils.StringExtract;
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
* object, extract international strings from the file and read output as a
* stream of UTF-8 strings as encoded bytes.
*
* <p/>
* Currently not-thread safe (reusing static buffers for efficiency)
*/
class AbstractFileStringIntStream extends InputStream {
class AbstractFileStringIntStream extends InputStream {
private AbstractFile content;
private final byte[] oneCharBuf = new byte[1];
private final StringExtract stringExtractor;
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 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()
@ -59,14 +61,14 @@ import org.sleuthkit.datamodel.TskCoreException;
* strings, then to byte stream, for specified script, auto-detected 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 scripts a list of scripts to consider
* @param extractUTF8 whether to extract utf8 encoding
* @param content input content to process and turn into a stream to convert into strings
* @param scripts a list of scripts to consider
* @param extractUTF8 whether to extract utf8 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,
boolean extractUTF16, Charset outCharset) {
public AbstractFileStringIntStream(AbstractFile content, List<SCRIPT> scripts, boolean extractUTF8,
boolean extractUTF16, Charset outCharset) {
this.content = content;
this.stringExtractor = new StringExtract();
this.stringExtractor.setEnabledScripts(scripts);
@ -100,7 +102,7 @@ import org.sleuthkit.datamodel.TskCoreException;
} else if (len == 0) {
return 0;
}
if (extractUTF8 == false && extractUTF16 == false) {
return -1;
}
@ -124,22 +126,22 @@ import org.sleuthkit.datamodel.TskCoreException;
//convert more strings, store in buffer
long toRead = 0;
//int shiftSize = 0;
//if (lastExtractResult != null && lastExtractResult.getTextLength() != 0
// && (shiftSize = FILE_BUF_SIZE - lastExtractResult.getFirstUnprocessedOff()) > 0) {
////a string previously extracted
////shift the fileReadBuff past last bytes extracted
////read only what's needed to fill the buffer
////to avoid loosing chars and breaking or corrupting potential strings - preserve byte stream continuity
//byte[] temp = new byte[shiftSize];
//System.arraycopy(fileReadBuff, lastExtractResult.getFirstUnprocessedOff(),
// temp, 0, shiftSize);
//System.arraycopy(temp, 0, fileReadBuff, 0, shiftSize);
//toRead = Math.min(lastExtractResult.getFirstUnprocessedOff(), fileSize - fileReadOffset);
//lastExtractResult = null;
// && (shiftSize = FILE_BUF_SIZE - lastExtractResult.getFirstUnprocessedOff()) > 0) {
////a string previously extracted
////shift the fileReadBuff past last bytes extracted
////read only what's needed to fill the buffer
////to avoid loosing chars and breaking or corrupting potential strings - preserve byte stream continuity
//byte[] temp = new byte[shiftSize];
//System.arraycopy(fileReadBuff, lastExtractResult.getFirstUnprocessedOff(),
// temp, 0, shiftSize);
//System.arraycopy(temp, 0, fileReadBuff, 0, shiftSize);
//toRead = Math.min(lastExtractResult.getFirstUnprocessedOff(), fileSize - fileReadOffset);
//lastExtractResult = null;
//} else {
//fill up entire fileReadBuff fresh
toRead = Math.min(FILE_BUF_SIZE, fileSize - fileReadOffset);
//fill up entire fileReadBuff fresh
toRead = Math.min(FILE_BUF_SIZE, fileSize - fileReadOffset);
//}
int read = content.read(fileReadBuff, fileReadOffset, toRead);
if (read == -1 || read == 0) {
@ -173,7 +175,7 @@ import org.sleuthkit.datamodel.TskCoreException;
//return part or all of convert buff to user
final int toCopy = Math.min(convertBuffRemain, len - offsetUser);
System.arraycopy(convertBuff, convertBuffOffset, b, offsetUser, toCopy);
//DEBUG
/*
if (toCopy > 0) {
@ -182,12 +184,12 @@ import org.sleuthkit.datamodel.TskCoreException;
debug.close();
}
*/
convertBuffOffset += toCopy;
offsetUser += toCopy;
bytesToUser += toCopy;
}
//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.InputStream;
import java.nio.charset.Charset;
import org.sleuthkit.autopsy.coreutils.Logger;
import org.sleuthkit.autopsy.coreutils.StringExtract;
import org.sleuthkit.datamodel.AbstractFile;
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()
*
* <p/>
* 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.
*
* <p/>
* For other script/languages support and better encoding detection use AbstractFileStringIntStream streaming class,
* which wraps around StringExtract extractor.
*/
class AbstractFileStringStream extends InputStream {
class AbstractFileStringStream extends InputStream {
//args
private AbstractFile content;
@ -53,7 +54,8 @@ import org.sleuthkit.datamodel.TskException;
private int tempStringLen = 0;
private boolean isEOF = false;
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 static final byte[] oneCharBuf = new byte[1];
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
*
* @param content to extract strings from
* @param outputCharset target encoding to index as
* @param content to extract strings from
* @param outputCharset target encoding to index as
* @param preserveOnBuffBoundary whether to preserve or split string on a
* buffer boundary. If false, will pack into read buffer up to max.
* possible, potentially splitting a string. If false, the string will be
* preserved for next read.
* buffer boundary. If false, will pack into read buffer up to max.
* possible, potentially splitting a string. If false, the string will be
* preserved for next read.
*/
public AbstractFileStringStream(AbstractFile content, Charset outputCharset, boolean preserveOnBuffBoundary) {
this.content = content;
@ -81,7 +83,7 @@ import org.sleuthkit.datamodel.TskException;
* Construct new string stream from FsContent Do not attempt to fill entire
* 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
*/
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.TimeoutException;
import java.util.logging.Level;
import org.sleuthkit.autopsy.coreutils.Logger;
import org.sleuthkit.autopsy.ingest.IngestModuleAbstractFile;
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
* (for unexpected/corrupt content) using a timeout mechanism. If Tika
* extraction succeeds, chunks are indexed with Solr.
*
* <p/>
* This Tika extraction/chunking utility is useful for large files of Tika
* parsers-supported content type.
*
*/
class AbstractFileTikaTextExtract implements AbstractFileExtract {
@ -139,13 +139,15 @@ class AbstractFileTikaTextExtract implements AbstractFileExtract {
future.get(Ingester.getTimeout(sourceFile.getSize()), TimeUnit.SECONDS);
} catch (TimeoutException te) {
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);
logger.log(Level.WARNING, msg);
throw new IngesterException(msg);
} catch (Exception ex) {
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);
logger.log(Level.WARNING, msg);
throw new IngesterException(msg);
@ -242,12 +244,14 @@ class AbstractFileTikaTextExtract implements AbstractFileExtract {
module.checkRunCommitSearch();
}
} 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);
logger.log(Level.WARNING, msg);
success = false;
} 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);
logger.log(Level.WARNING, msg);
success = false;
@ -327,11 +331,15 @@ class AbstractFileTikaTextExtract implements AbstractFileExtract {
try {
reader = tika.parse(stream, meta);
} 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;
reader = null;
} 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;
reader = null;
}

View File

@ -33,7 +33,8 @@ import org.openide.util.NbBundle;
*/
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;
AbstractKeywordSearchPerformer() {
@ -86,19 +87,26 @@ abstract class AbstractKeywordSearchPerformer extends javax.swing.JPanel impleme
if (filesIndexed == 0) {
if (isRunning) {
KeywordSearchUtil.displayDialog(keywordSearchErrorDialogHeader, NbBundle.getMessage(this.getClass(),
"AbstractKeywordSearchPerformer.search.noFilesInIdxMsg",
KeywordSearchSettings.getUpdateFrequency().getTime()), KeywordSearchUtil.DIALOG_MESSAGE_TYPE.ERROR);
"AbstractKeywordSearchPerformer.search.noFilesInIdxMsg",
KeywordSearchSettings
.getUpdateFrequency()
.getTime()),
KeywordSearchUtil.DIALOG_MESSAGE_TYPE.ERROR);
} else {
KeywordSearchUtil.displayDialog(keywordSearchErrorDialogHeader, NbBundle.getMessage(this.getClass(),
"AbstractKeywordSearchPerformer.search.noFilesIdxdMsg"), KeywordSearchUtil.DIALOG_MESSAGE_TYPE.ERROR);
"AbstractKeywordSearchPerformer.search.noFilesIdxdMsg"),
KeywordSearchUtil.DIALOG_MESSAGE_TYPE.ERROR);
}
return;
}
//check if keyword search module ingest is running (indexing, etc)
if (isRunning) {
if (KeywordSearchUtil.displayConfirmDialog(org.openide.util.NbBundle.getMessage(this.getClass(), "AbstractKeywordSearchPerformer.search.searchIngestInProgressTitle"),
NbBundle.getMessage(this.getClass(), "AbstractKeywordSearchPerformer.search.ingestInProgressBody"), KeywordSearchUtil.DIALOG_MESSAGE_TYPE.WARN) == false) {
if (KeywordSearchUtil.displayConfirmDialog(org.openide.util.NbBundle.getMessage(this.getClass(),
"AbstractKeywordSearchPerformer.search.searchIngestInProgressTitle"),
NbBundle.getMessage(this.getClass(),
"AbstractKeywordSearchPerformer.search.ingestInProgressBody"),
KeywordSearchUtil.DIALOG_MESSAGE_TYPE.WARN) == false) {
return;
}
}
@ -108,8 +116,8 @@ abstract class AbstractKeywordSearchPerformer extends javax.swing.JPanel impleme
final List<Keyword> keywords = getQueryList();
if (keywords.isEmpty()) {
KeywordSearchUtil.displayDialog(keywordSearchErrorDialogHeader, NbBundle.getMessage(this.getClass(),
"AbstractKeywordSearchPerformer.search.emptyKeywordErrorBody"),
KeywordSearchUtil.DIALOG_MESSAGE_TYPE.ERROR);
"AbstractKeywordSearchPerformer.search.emptyKeywordErrorBody"),
KeywordSearchUtil.DIALOG_MESSAGE_TYPE.ERROR);
return;
}
man = new KeywordSearchQueryManager(keywords, Presentation.FLAT);
@ -123,7 +131,8 @@ abstract class AbstractKeywordSearchPerformer extends javax.swing.JPanel impleme
final String queryText = getQueryText();
if (queryText == null || queryText.trim().equals("")) {
KeywordSearchUtil.displayDialog(keywordSearchErrorDialogHeader, NbBundle.getMessage(this.getClass(),
"AbstractKeywordSearchPerformer.search.pleaseEnterKeywordBody"), KeywordSearchUtil.DIALOG_MESSAGE_TYPE.ERROR);
"AbstractKeywordSearchPerformer.search.pleaseEnterKeywordBody"),
KeywordSearchUtil.DIALOG_MESSAGE_TYPE.ERROR);
return;
}
man = new KeywordSearchQueryManager(getQueryText(), queryType, Presentation.FLAT);
@ -133,7 +142,8 @@ abstract class AbstractKeywordSearchPerformer extends javax.swing.JPanel impleme
man.execute();
} else {
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.Reader;
import java.nio.charset.Charset;
import org.sleuthkit.autopsy.coreutils.Logger;
import org.apache.solr.common.util.ContentStream;
import org.sleuthkit.datamodel.AbstractContent;
@ -32,30 +33,30 @@ import org.sleuthkit.datamodel.AbstractContent;
* Stream of bytes representing string with specified encoding
* to feed into Solr as ContentStream
*/
class ByteContentStream implements ContentStream {
class ByteContentStream implements ContentStream {
//input
private byte[] content; //extracted subcontent
private long contentSize;
private AbstractContent aContent; //origin
private Charset charset; //output byte stream charset of encoded strings
private InputStream stream;
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.aContent = aContent;
this.charset = charset;
stream = new ByteArrayInputStream(content, 0, (int)contentSize);
stream = new ByteArrayInputStream(content, 0, (int) contentSize);
}
public byte[] getByteContent() {
return content;
}
public AbstractContent getSourceContent() {
return aContent;
}
@ -95,10 +96,9 @@ class ByteContentStream implements ContentStream {
@Override
protected void finalize() throws Throwable {
super.finalize();
stream.close();
}
}

View File

@ -21,6 +21,7 @@ package org.sleuthkit.autopsy.keywordsearch;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import org.sleuthkit.datamodel.AbstractFile;
/**
@ -85,8 +86,9 @@ class ContentHit {
/**
* Identify the list of files with the first chunk that has a hit
*
* @param hits
* @return
* @return
*/
static Map<AbstractFile, Integer> flattenResults(List<ContentHit> hits) {
Map<AbstractFile, Integer> ret = new LinkedHashMap<AbstractFile, Integer>();
@ -99,7 +101,7 @@ class ContentHit {
return ret;
}
//flatten results to get unique AbstractFile per hit, with first chunk id encountered
static LinkedHashMap<AbstractFile, Integer> flattenResults(Map<String, List<ContentHit>> results) {
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.sleuthkit.autopsy.coreutils.Logger;
import javax.swing.JMenuItem;
import javax.swing.JTextPane;
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.HTMLFactory;
import javax.swing.text.html.StyleSheet;
import org.netbeans.api.progress.ProgressHandle;
import org.netbeans.api.progress.ProgressHandleFactory;
import org.sleuthkit.autopsy.coreutils.EscapeUtil;
@ -64,7 +66,7 @@ class ExtractedContentPanel extends javax.swing.JPanel {
}
private void customizeComponents() {
HTMLEditorKit editorKit = new HTMLEditorKit() {
@Override
public ViewFactory getViewFactory() {
@ -92,7 +94,8 @@ class ExtractedContentPanel extends javax.swing.JPanel {
};
} else if (v instanceof ParagraphView) {
return new ParagraphView(e) {
protected SizeRequirements calculateMinorAxisRequirements(int axis, SizeRequirements r) {
protected SizeRequirements calculateMinorAxisRequirements(int axis,
SizeRequirements r) {
if (r == null) {
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
// similar to what is in the 'String View' content viewer.
StyleSheet ss = editorKit.getStyleSheet();
ss.addRule("body {font-size: 8.5px;}");
extractedTextPane.setEditorKit(editorKit);
sourceComboBox.addItemListener(new ItemListener() {
@ -162,176 +165,239 @@ class ExtractedContentPanel extends javax.swing.JPanel {
copyMenuItem = new javax.swing.JMenuItem();
selectAllMenuItem = new javax.swing.JMenuItem();
jScrollPane1 = new javax.swing.JScrollPane();
extractedTextPane = new JTextPane(){
extractedTextPane = new JTextPane() {
public boolean getScrollableTracksViewportWidth() {
return (getSize().width < 400);
}};
sourceComboBox = new javax.swing.JComboBox();
hitLabel = new javax.swing.JLabel();
hitCountLabel = new javax.swing.JLabel();
hitOfLabel = new javax.swing.JLabel();
hitTotalLabel = new javax.swing.JLabel();
hitButtonsLabel = new javax.swing.JLabel();
hitPreviousButton = new javax.swing.JButton();
hitNextButton = new javax.swing.JButton();
pageButtonsLabel = new javax.swing.JLabel();
pagePreviousButton = new javax.swing.JButton();
pageNextButton = new javax.swing.JButton();
pagesLabel = new javax.swing.JLabel();
pageCurLabel = new javax.swing.JLabel();
pageOfLabel = new javax.swing.JLabel();
pageTotalLabel = new javax.swing.JLabel();
}
};
sourceComboBox = new javax.swing.JComboBox();
hitLabel = new javax.swing.JLabel();
hitCountLabel = new javax.swing.JLabel();
hitOfLabel = new javax.swing.JLabel();
hitTotalLabel = new javax.swing.JLabel();
hitButtonsLabel = new javax.swing.JLabel();
hitPreviousButton = new javax.swing.JButton();
hitNextButton = new javax.swing.JButton();
pageButtonsLabel = new javax.swing.JLabel();
pagePreviousButton = new javax.swing.JButton();
pageNextButton = new javax.swing.JButton();
pagesLabel = new javax.swing.JLabel();
pageCurLabel = 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
rightClickMenu.add(copyMenuItem);
copyMenuItem.setText(org.openide.util.NbBundle.getMessage(ExtractedContentPanel.class,
"ExtractedContentPanel.copyMenuItem.text")); // NOI18N
rightClickMenu.add(copyMenuItem);
selectAllMenuItem.setText(org.openide.util.NbBundle.getMessage(ExtractedContentPanel.class, "ExtractedContentPanel.selectAllMenuItem.text")); // NOI18N
rightClickMenu.add(selectAllMenuItem);
selectAllMenuItem.setText(org.openide.util.NbBundle.getMessage(ExtractedContentPanel.class,
"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.setPreferredSize(new java.awt.Dimension(700, 400));
jScrollPane1.setBackground(new java.awt.Color(255, 255, 255));
jScrollPane1.setPreferredSize(new java.awt.Dimension(700, 400));
extractedTextPane.setEditable(false);
extractedTextPane.setAutoscrolls(false);
extractedTextPane.setMaximumSize(new java.awt.Dimension(2000, 2000));
extractedTextPane.setPreferredSize(new java.awt.Dimension(700, 400));
jScrollPane1.setViewportView(extractedTextPane);
extractedTextPane.setEditable(false);
extractedTextPane.setAutoscrolls(false);
extractedTextPane.setMaximumSize(new java.awt.Dimension(2000, 2000));
extractedTextPane.setPreferredSize(new java.awt.Dimension(700, 400));
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.setToolTipText(org.openide.util.NbBundle.getMessage(ExtractedContentPanel.class, "ExtractedContentPanel.hitLabel.toolTipText")); // NOI18N
hitLabel.setText(org.openide.util.NbBundle.getMessage(ExtractedContentPanel.class,
"ExtractedContentPanel.hitLabel.text")); // NOI18N
hitLabel.setToolTipText(org.openide.util.NbBundle.getMessage(ExtractedContentPanel.class,
"ExtractedContentPanel.hitLabel.toolTipText")); // NOI18N
hitCountLabel.setHorizontalAlignment(javax.swing.SwingConstants.CENTER);
hitCountLabel.setText(org.openide.util.NbBundle.getMessage(ExtractedContentPanel.class, "ExtractedContentPanel.hitCountLabel.text")); // NOI18N
hitCountLabel.setMaximumSize(new java.awt.Dimension(18, 14));
hitCountLabel.setMinimumSize(new java.awt.Dimension(18, 14));
hitCountLabel.setPreferredSize(new java.awt.Dimension(18, 14));
hitCountLabel.setHorizontalAlignment(javax.swing.SwingConstants.CENTER);
hitCountLabel.setText(org.openide.util.NbBundle.getMessage(ExtractedContentPanel.class,
"ExtractedContentPanel.hitCountLabel.text")); // NOI18N
hitCountLabel.setMaximumSize(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.setText(org.openide.util.NbBundle.getMessage(ExtractedContentPanel.class, "ExtractedContentPanel.hitTotalLabel.text")); // NOI18N
hitTotalLabel.setMaximumSize(new java.awt.Dimension(18, 14));
hitTotalLabel.setMinimumSize(new java.awt.Dimension(18, 14));
hitTotalLabel.setPreferredSize(new java.awt.Dimension(18, 14));
hitTotalLabel.setHorizontalAlignment(javax.swing.SwingConstants.CENTER);
hitTotalLabel.setText(org.openide.util.NbBundle.getMessage(ExtractedContentPanel.class,
"ExtractedContentPanel.hitTotalLabel.text")); // NOI18N
hitTotalLabel.setMaximumSize(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.setText(org.openide.util.NbBundle.getMessage(ExtractedContentPanel.class, "ExtractedContentPanel.hitPreviousButton.text")); // NOI18N
hitPreviousButton.setBorder(javax.swing.BorderFactory.createEmptyBorder(1, 1, 1, 1));
hitPreviousButton.setBorderPainted(false);
hitPreviousButton.setContentAreaFilled(false);
hitPreviousButton.setDisabledIcon(new javax.swing.ImageIcon(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
hitPreviousButton.setIcon(new javax.swing.ImageIcon(
getClass().getResource("/org/sleuthkit/autopsy/keywordsearch/btn_step_back.png"))); // NOI18N
hitPreviousButton.setText(org.openide.util.NbBundle.getMessage(ExtractedContentPanel.class,
"ExtractedContentPanel.hitPreviousButton.text")); // NOI18N
hitPreviousButton.setBorder(javax.swing.BorderFactory.createEmptyBorder(1, 1, 1, 1));
hitPreviousButton.setBorderPainted(false);
hitPreviousButton.setContentAreaFilled(false);
hitPreviousButton.setDisabledIcon(new javax.swing.ImageIcon(
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.setText(org.openide.util.NbBundle.getMessage(ExtractedContentPanel.class, "ExtractedContentPanel.hitNextButton.text")); // NOI18N
hitNextButton.setBorder(javax.swing.BorderFactory.createEmptyBorder(1, 1, 1, 1));
hitNextButton.setBorderPainted(false);
hitNextButton.setContentAreaFilled(false);
hitNextButton.setDisabledIcon(new javax.swing.ImageIcon(getClass().getResource("/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
hitNextButton.setIcon(new javax.swing.ImageIcon(
getClass().getResource("/org/sleuthkit/autopsy/keywordsearch/btn_step_forward.png"))); // NOI18N
hitNextButton.setText(org.openide.util.NbBundle.getMessage(ExtractedContentPanel.class,
"ExtractedContentPanel.hitNextButton.text")); // NOI18N
hitNextButton.setBorder(javax.swing.BorderFactory.createEmptyBorder(1, 1, 1, 1));
hitNextButton.setBorderPainted(false);
hitNextButton.setContentAreaFilled(false);
hitNextButton.setDisabledIcon(new javax.swing.ImageIcon(getClass().getResource(
"/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.setText(org.openide.util.NbBundle.getMessage(ExtractedContentPanel.class, "ExtractedContentPanel.pagePreviousButton.text")); // NOI18N
pagePreviousButton.setActionCommand(org.openide.util.NbBundle.getMessage(ExtractedContentPanel.class, "ExtractedContentPanel.pagePreviousButton.actionCommand")); // NOI18N
pagePreviousButton.setBorder(javax.swing.BorderFactory.createEmptyBorder(1, 1, 1, 1));
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));
pagePreviousButton.setIcon(new javax.swing.ImageIcon(
getClass().getResource("/org/sleuthkit/autopsy/keywordsearch/btn_step_back.png"))); // NOI18N
pagePreviousButton.setText(org.openide.util.NbBundle.getMessage(ExtractedContentPanel.class,
"ExtractedContentPanel.pagePreviousButton.text")); // NOI18N
pagePreviousButton.setActionCommand(org.openide.util.NbBundle.getMessage(ExtractedContentPanel.class,
"ExtractedContentPanel.pagePreviousButton.actionCommand")); // NOI18N
pagePreviousButton.setBorder(javax.swing.BorderFactory.createEmptyBorder(1, 1, 1, 1));
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.setText(org.openide.util.NbBundle.getMessage(ExtractedContentPanel.class, "ExtractedContentPanel.pageNextButton.text")); // NOI18N
pageNextButton.setBorder(javax.swing.BorderFactory.createEmptyBorder(1, 1, 1, 1));
pageNextButton.setBorderPainted(false);
pageNextButton.setContentAreaFilled(false);
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));
pageNextButton.setIcon(new javax.swing.ImageIcon(
getClass().getResource("/org/sleuthkit/autopsy/keywordsearch/btn_step_forward.png"))); // NOI18N
pageNextButton.setText(org.openide.util.NbBundle.getMessage(ExtractedContentPanel.class,
"ExtractedContentPanel.pageNextButton.text")); // NOI18N
pageNextButton.setBorder(javax.swing.BorderFactory.createEmptyBorder(1, 1, 1, 1));
pageNextButton.setBorderPainted(false);
pageNextButton.setContentAreaFilled(false);
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.setText(org.openide.util.NbBundle.getMessage(ExtractedContentPanel.class, "ExtractedContentPanel.pageCurLabel.text")); // NOI18N
pageCurLabel.setHorizontalAlignment(javax.swing.SwingConstants.CENTER);
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.setText(org.openide.util.NbBundle.getMessage(ExtractedContentPanel.class, "ExtractedContentPanel.pageTotalLabel.text")); // NOI18N
pageTotalLabel.setHorizontalAlignment(javax.swing.SwingConstants.CENTER);
pageTotalLabel.setText(org.openide.util.NbBundle.getMessage(ExtractedContentPanel.class,
"ExtractedContentPanel.pageTotalLabel.text")); // NOI18N
javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
this.setLayout(layout);
layout.setHorizontalGroup(
javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
this.setLayout(layout);
layout.setHorizontalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup()
.addContainerGap()
.addComponent(hitLabel)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
.addComponent(hitCountLabel, javax.swing.GroupLayout.PREFERRED_SIZE, 30, javax.swing.GroupLayout.PREFERRED_SIZE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
.addComponent(hitOfLabel)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
.addComponent(hitTotalLabel, javax.swing.GroupLayout.PREFERRED_SIZE, 30, javax.swing.GroupLayout.PREFERRED_SIZE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
.addComponent(hitButtonsLabel)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(hitPreviousButton, javax.swing.GroupLayout.PREFERRED_SIZE, 23, javax.swing.GroupLayout.PREFERRED_SIZE)
.addGap(0, 0, 0)
.addComponent(hitNextButton, javax.swing.GroupLayout.PREFERRED_SIZE, 23, javax.swing.GroupLayout.PREFERRED_SIZE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
.addComponent(pagesLabel)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(pageCurLabel, javax.swing.GroupLayout.PREFERRED_SIZE, 30, javax.swing.GroupLayout.PREFERRED_SIZE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
.addComponent(pageOfLabel)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(pageTotalLabel, javax.swing.GroupLayout.PREFERRED_SIZE, 30, javax.swing.GroupLayout.PREFERRED_SIZE)
.addGap(18, 18, 18)
.addComponent(pageButtonsLabel)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
.addComponent(pagePreviousButton)
.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(
.addGroup(layout.createSequentialGroup()
.addContainerGap()
.addComponent(hitLabel)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
.addComponent(hitCountLabel, javax.swing.GroupLayout.PREFERRED_SIZE, 30,
javax.swing.GroupLayout.PREFERRED_SIZE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
.addComponent(hitOfLabel)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
.addComponent(hitTotalLabel, javax.swing.GroupLayout.PREFERRED_SIZE, 30,
javax.swing.GroupLayout.PREFERRED_SIZE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
.addComponent(hitButtonsLabel)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(hitPreviousButton, javax.swing.GroupLayout.PREFERRED_SIZE, 23,
javax.swing.GroupLayout.PREFERRED_SIZE)
.addGap(0, 0, 0)
.addComponent(hitNextButton, javax.swing.GroupLayout.PREFERRED_SIZE, 23,
javax.swing.GroupLayout.PREFERRED_SIZE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
.addComponent(pagesLabel)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(pageCurLabel, javax.swing.GroupLayout.PREFERRED_SIZE, 30,
javax.swing.GroupLayout.PREFERRED_SIZE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
.addComponent(pageOfLabel)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(pageTotalLabel, javax.swing.GroupLayout.PREFERRED_SIZE, 30,
javax.swing.GroupLayout.PREFERRED_SIZE)
.addGap(18, 18, 18)
.addComponent(pageButtonsLabel)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
.addComponent(pagePreviousButton)
.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)
.addGroup(layout.createSequentialGroup()
.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)
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
.addComponent(hitCountLabel, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addComponent(hitOfLabel)
.addComponent(hitTotalLabel, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addComponent(hitLabel)
.addComponent(hitButtonsLabel))
.addComponent(hitPreviousButton, javax.swing.GroupLayout.PREFERRED_SIZE, 23, javax.swing.GroupLayout.PREFERRED_SIZE)
.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
.addGroup(layout.createSequentialGroup()
.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)
.addGroup(layout.createParallelGroup(
javax.swing.GroupLayout.Alignment.BASELINE)
.addComponent(hitCountLabel,
javax.swing.GroupLayout.PREFERRED_SIZE,
javax.swing.GroupLayout.DEFAULT_SIZE,
javax.swing.GroupLayout.PREFERRED_SIZE)
.addComponent(hitOfLabel)
.addComponent(hitTotalLabel,
javax.swing.GroupLayout.PREFERRED_SIZE,
javax.swing.GroupLayout.DEFAULT_SIZE,
javax.swing.GroupLayout.PREFERRED_SIZE)
.addComponent(hitLabel)
.addComponent(hitButtonsLabel))
.addComponent(hitPreviousButton,
javax.swing.GroupLayout.PREFERRED_SIZE, 23,
javax.swing.GroupLayout.PREFERRED_SIZE)
.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
private javax.swing.JMenuItem copyMenuItem;
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.
* Different sources will markup the text in different ways.
*
* Return the types of mark up sources that this viewer knows about.
* Different sources will markup the text in different ways.
*
* @return currently available sources on the panel
*/
public List<MarkupSource> getSources() {
@ -395,6 +461,7 @@ class ExtractedContentPanel extends javax.swing.JPanel {
/**
* Get the source selected in the combo box
*
* @return currently selected Source
*/
public MarkupSource getSelectedSource() {
@ -438,7 +505,6 @@ class ExtractedContentPanel extends javax.swing.JPanel {
}
/**
*
* @param current, current hit to update the display with
*/
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
*/
void updateTotaMatcheslDisplay(int total) {
@ -462,7 +527,6 @@ class ExtractedContentPanel extends javax.swing.JPanel {
}
/**
*
* @param current, current page to update the display with
*/
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
*/
void updateTotalPageslDisplay(int total) {

View File

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

View File

@ -94,7 +94,8 @@ class HighlightedMatchesSource implements MarkupSource, HighlightLookup {
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.group = group;
}
@ -345,11 +346,13 @@ class HighlightedMatchesSource implements MarkupSource, HighlightLookup {
final String filterQuery = Server.Schema.ID.toString() + ":" + contentIdStr;
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.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
q.setParam("hl.useFastVectorHighlighter", "on"); //fast highlighter scales better than standard one
@ -439,6 +442,7 @@ class HighlightedMatchesSource implements MarkupSource, HighlightLookup {
return buf.toString();
}
//dummy instance for Lookup only
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.TimeoutException;
import java.util.logging.Level;
import org.apache.solr.client.solrj.SolrRequest.METHOD;
import org.apache.solr.client.solrj.SolrServerException;
import org.apache.solr.client.solrj.request.AbstractUpdateRequest;
@ -70,10 +71,10 @@ class Ingester {
private final Server solrServer = KeywordSearch.getServer();
private final GetContentFieldsV getContentFieldsV = new GetContentFieldsV();
private static Ingester instance;
//for ingesting chunk as SolrInputDocument (non-content-streaming, by-pass tika)
//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 static final String docContentEncoding = "UTF-8";
@ -105,7 +106,7 @@ class Ingester {
*
* @param afscs File AbstractFileStringContentStream to ingest
* @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 {
Map<String, String> params = getContentFields(afscs.getSourceContent());
@ -121,7 +122,7 @@ class Ingester {
*
* @param fe AbstractFileExtract to ingest
* @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 {
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
* 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
* estimation
* estimation
* @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 {
AbstractContent sourceContent = bcs.getSourceContent();
@ -148,7 +149,7 @@ class Ingester {
//overwrite id with the chunk id
params.put(Server.Schema.ID.toString(),
Server.getChunkIdString(sourceContent.getId(), fec.getChunkId()));
Server.getChunkIdString(sourceContent.getId(), fec.getChunkId()));
ingest(bcs, params, size);
}
@ -159,11 +160,11 @@ class Ingester {
* file is a directory or ingestContent is set to false, the file name is
* indexed only.
*
* @param file File to ingest
* @param file File to ingest
* @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
* file, but the Solr server is probably fine.
* file, but the Solr server is probably fine.
*/
void ingest(AbstractFile file, boolean ingestContent) throws IngesterException {
if (ingestContent == false || file.isDir()) {
@ -189,11 +190,11 @@ class Ingester {
private class GetContentFieldsV extends ContentVisitor.Default<Map<String, String>> {
private SleuthkitCase curCase = null;
GetContentFieldsV() {
curCase = Case.getCurrentCase().getSleuthkitCase();
}
@Override
protected Map<String, String> defaultVisit(Content cntnt) {
return new HashMap<String, String>();
@ -205,7 +206,7 @@ class Ingester {
getCommonFileContentFields(params, f);
return params;
}
@Override
public Map<String, String> visit(DerivedFile df) {
Map<String, String> params = getCommonFields(df);
@ -225,7 +226,7 @@ class Ingester {
// layout files do not have times
return getCommonFields(lf);
}
@Override
public Map<String, String> visit(LocalFile lf) {
Map<String, String> params = getCommonFields(lf);
@ -240,7 +241,7 @@ class Ingester {
params.put(Server.Schema.CRTIME.toString(), ContentUtils.getStringTimeISO8601(file.getCrtime(), file));
return params;
}
private Map<String, String> getCommonFields(AbstractFile af) {
Map<String, String> params = new HashMap<String, String>();
@ -259,31 +260,31 @@ class Ingester {
}
}
/**
* Indexing method that bypasses Tika, assumes pure text
* It reads and converts the entire content stream to string, assuming UTF8
* since we can't use streaming approach for Solr /update handler.
* 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
* 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
*
*
* @param cs
* @param fields
* @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 {
if (fields.get(Server.Schema.IMAGE_ID.toString()) == null) {
//skip the file, image id unknown
String msg = "Skipping indexing the file, unknown image id, for file: " + cs.getName();
logger.log(Level.SEVERE, msg);
throw new IngesterException(msg);
}
SolrInputDocument updateDoc = new SolrInputDocument();
for (String key : fields.keySet()) {
@ -292,9 +293,9 @@ class Ingester {
//using size here, but we are no longer ingesting entire files
//size is normally a chunk size, up to 1MB
if (size > 0) {
InputStream is = null;
int read = 0;
try {
@ -306,7 +307,8 @@ class Ingester {
try {
is.close();
} 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 {
updateDoc.addField(Server.Schema.CONTENT.toString(), "");
}
}
else {
} else {
//no content, such as case when 0th chunk indexed
updateDoc.addField(Server.Schema.CONTENT.toString(), "");
}
try {
//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
* implementing ContentStream
*
* @param cs ContentStream to ingest
* @param cs ContentStream to ingest
* @param fields content specific fields
* @param size size of the content - used to determine the Solr timeout, not
* used to populate meta-data
*
* @param size size of the content - used to determine the Solr timeout, not
* used to populate meta-data
* @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 {
final ContentStreamUpdateRequest up = new ContentStreamUpdateRequest("/update/extract");
@ -373,9 +373,12 @@ class Ingester {
logger.log(Level.WARNING, "Solr timeout encountered, trying to restart Solr");
//restart may be needed to recover from some error conditions
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) {
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;
}
@ -458,7 +461,8 @@ class Ingester {
// When Tika has problems with a document, it throws a server error
// but it's okay to continue with other documents
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 {
// shouldn't get any other error codes
throw ex;
@ -486,7 +490,7 @@ class Ingester {
/**
* Helper to set document fields
*
* @param up request with document
* @param up request with document
* @param fields map of field-names->values
*/
private static void setFields(ContentStreamUpdateRequest up, Map<String, String> fields) {

View File

@ -19,6 +19,7 @@
package org.sleuthkit.autopsy.keywordsearch;
import java.util.logging.Level;
import org.openide.modules.ModuleInstall;
import org.openide.util.NbBundle;
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
* application is closed.
*
* <p/>
* In addition, the default KeywordSearch config files (NSRL, Options, Scripts)
* are generated here, if they config files do not already exist.
*/
@ -202,7 +203,9 @@ class Installer extends ModuleInstall {
WindowManager.getDefault().invokeWhenUIReady(new Runnable() {
@Override
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);
}
});
@ -212,7 +215,8 @@ class Installer extends ModuleInstall {
WindowManager.getDefault().invokeWhenUIReady(new Runnable() {
@Override
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);
}
});
@ -222,7 +226,10 @@ class Installer extends ModuleInstall {
WindowManager.getDefault().invokeWhenUIReady(new Runnable() {
@Override
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);

View File

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

View File

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

View File

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

View File

@ -27,6 +27,7 @@ import java.util.logging.FileHandler;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.logging.SimpleFormatter;
import org.openide.util.Exceptions;
import org.sleuthkit.autopsy.casemodule.Case;
import org.sleuthkit.autopsy.coreutils.PlatformUtil;
@ -66,7 +67,8 @@ class KeywordSearch {
static {
try {
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);
tikaLogHandler.setFormatter(new SimpleFormatter());
tikaLogHandler.setEncoding(PlatformUtil.getLogFileEncoding());
@ -88,16 +90,16 @@ class KeywordSearch {
static Logger getTikaLogger() {
return TIKA_LOGGER;
}
public static void addNumIndexedFilesChangeListener(PropertyChangeListener l) {
changeSupport.addPropertyChangeListener(NUM_FILES_CHANGE_EVT, l);
}
public static void removeNumIndexedFilesChangeListener(PropertyChangeListener l) {
changeSupport.removePropertyChangeListener(l);
}
static void fireNumIndexedFilesChange(Integer oldNum, Integer 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.event.ActionEvent;
import javax.swing.AbstractAction;
import org.openide.util.actions.Presenter;
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.WindowEvent;
import java.awt.event.WindowListener;
import org.openide.util.HelpCtx;
import org.openide.util.actions.CallableSystemAction;
import org.sleuthkit.autopsy.corecomponents.AdvancedConfigurationDialog;
@ -30,9 +31,10 @@ import org.sleuthkit.autopsy.corecomponents.AdvancedConfigurationDialog;
/**
* System action to open the KeywordSearch Options panel.
*/
class KeywordSearchConfigurationAction extends CallableSystemAction{
private static final String ACTION_NAME = org.openide.util.NbBundle.getMessage(KeywordSearchPanel.class, "ListBundleConfig");
class KeywordSearchConfigurationAction extends CallableSystemAction {
private static final String ACTION_NAME = org.openide.util.NbBundle
.getMessage(KeywordSearchPanel.class, "ListBundleConfig");
private KeywordSearchConfigurationPanel panel;
@Override
@ -59,9 +61,9 @@ class KeywordSearchConfigurationAction extends CallableSystemAction{
dialog.addWindowListener(exitListener);
dialog.display(panel);
}
private KeywordSearchConfigurationPanel getPanel() {
if(panel==null) {
if (panel == null) {
panel = new KeywordSearchConfigurationPanel();
}
return panel;
@ -76,7 +78,7 @@ class KeywordSearchConfigurationAction extends CallableSystemAction{
public HelpCtx getHelpCtx() {
return HelpCtx.DEFAULT_HELP;
}
@Override
protected boolean asynchronous() {
return false;

View File

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

View File

@ -41,11 +41,14 @@ class KeywordSearchConfigurationPanel1 extends javax.swing.JPanel implements Opt
KeywordSearchListsManagementPanel listsManagementPanel;
KeywordSearchEditListPanel editListPanel;
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");
/** Creates new form KeywordSearchConfigurationPanel1 */
private static final String KEYWORD_CONFIG_NAME = org.openide.util.NbBundle.getMessage(KeywordSearchPanel.class,
"ListBundleConfig");
/**
* Creates new form KeywordSearchConfigurationPanel1
*/
KeywordSearchConfigurationPanel1() {
initComponents();
customizeComponents();
setName(KEYWORD_CONFIG_NAME);
@ -57,12 +60,14 @@ class KeywordSearchConfigurationPanel1 extends javax.swing.JPanel implements Opt
listsManagementPanel.addListSelectionListener(editListPanel);
editListPanel.addDeleteButtonActionPerformed(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
if (KeywordSearchUtil.displayConfirmDialog(NbBundle.getMessage(this.getClass(), "KeywordSearchConfigurationPanel1.customizeComponents.title")
, NbBundle.getMessage(this.getClass(), "KeywordSearchConfigurationPanel1.customizeComponents.body" )
, KeywordSearchUtil.DIALOG_MESSAGE_TYPE.WARN) ) {
if (KeywordSearchUtil.displayConfirmDialog(NbBundle.getMessage(this.getClass(),
"KeywordSearchConfigurationPanel1.customizeComponents.title")
, NbBundle.getMessage(this.getClass(),
"KeywordSearchConfigurationPanel1.customizeComponents.body")
, KeywordSearchUtil.DIALOG_MESSAGE_TYPE.WARN)) {
KeywordSearchListsXML deleter = KeywordSearchListsXML.getCurrent();
String toDelete = editListPanel.getCurrentKeywordList().getName();
@ -73,9 +78,9 @@ class KeywordSearchConfigurationPanel1 extends javax.swing.JPanel implements Opt
}
}
});
editListPanel.addSaveButtonActionPerformed(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
final String FEATURE_NAME = "Save Keyword List";
@ -84,8 +89,9 @@ class KeywordSearchConfigurationPanel1 extends javax.swing.JPanel implements Opt
List<Keyword> keywords = currentKeywordList.getKeywords();
if (keywords.isEmpty()) {
KeywordSearchUtil.displayDialog(FEATURE_NAME, NbBundle.getMessage(this.getClass(), "KeywordSearchConfigurationPanel1.customizeComponents.keywordListEmptyErr"),
KeywordSearchUtil.DIALOG_MESSAGE_TYPE.INFO);
KeywordSearchUtil.displayDialog(FEATURE_NAME, NbBundle.getMessage(this.getClass(),
"KeywordSearchConfigurationPanel1.customizeComponents.keywordListEmptyErr"),
KeywordSearchUtil.DIALOG_MESSAGE_TYPE.INFO);
return;
}
@ -102,13 +108,18 @@ class KeywordSearchConfigurationPanel1 extends javax.swing.JPanel implements Opt
}
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;
}
boolean shouldAdd = false;
if (writer.listExists(listName)) {
boolean replace = KeywordSearchUtil.displayConfirmDialog(FEATURE_NAME, NbBundle.getMessage(this.getClass(), "KeywordSearchConfigurationPanel1.customizeComponents.kwListExistMsg", listName),
KeywordSearchUtil.DIALOG_MESSAGE_TYPE.WARN);
boolean replace = KeywordSearchUtil.displayConfirmDialog(FEATURE_NAME,
NbBundle.getMessage(this.getClass(),
"KeywordSearchConfigurationPanel1.customizeComponents.kwListExistMsg",
listName),
KeywordSearchUtil.DIALOG_MESSAGE_TYPE.WARN);
if (replace) {
shouldAdd = true;
}
@ -119,34 +130,38 @@ class KeywordSearchConfigurationPanel1 extends javax.swing.JPanel implements Opt
if (shouldAdd) {
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);
listsManagementPanel.resync();
}
});
mainSplitPane.setLeftComponent(listsManagementPanel);
mainSplitPane.setRightComponent(editListPanel);
mainSplitPane.revalidate();
mainSplitPane.repaint();
}
@Override
public void store() {
KeywordSearchListsXML.getCurrent().save(false);
//refresh the list viewer/searcher panel
KeywordSearchListsViewerPanel.getDefault().resync();
}
@Override
public void load() {
listsManagementPanel.load();
}
/** This method is called from within the constructor to
/**
* This method is called from within the constructor to
* initialize the form.
* WARNING: Do NOT modify this code. The content of this method is
* 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);
leftPanel.setLayout(leftPanelLayout);
leftPanelLayout.setHorizontalGroup(
leftPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGap(0, 275, Short.MAX_VALUE)
leftPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGap(0, 275, Short.MAX_VALUE)
);
leftPanelLayout.setVerticalGroup(
leftPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGap(0, 327, Short.MAX_VALUE)
leftPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGap(0, 327, Short.MAX_VALUE)
);
mainSplitPane.setLeftComponent(leftPanel);
@ -178,12 +193,12 @@ class KeywordSearchConfigurationPanel1 extends javax.swing.JPanel implements Opt
javax.swing.GroupLayout rightPanelLayout = new javax.swing.GroupLayout(rightPanel);
rightPanel.setLayout(rightPanelLayout);
rightPanelLayout.setHorizontalGroup(
rightPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGap(0, 318, Short.MAX_VALUE)
rightPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGap(0, 318, Short.MAX_VALUE)
);
rightPanelLayout.setVerticalGroup(
rightPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGap(0, 327, Short.MAX_VALUE)
rightPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGap(0, 327, Short.MAX_VALUE)
);
mainSplitPane.setRightComponent(rightPanel);
@ -191,12 +206,12 @@ class KeywordSearchConfigurationPanel1 extends javax.swing.JPanel implements Opt
javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
this.setLayout(layout);
layout.setHorizontalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(mainSplitPane)
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(mainSplitPane)
);
layout.setVerticalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(mainSplitPane)
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(mainSplitPane)
);
}// </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.JPanel rightPanel;
// 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.PropertyChangeListener;
import java.util.logging.Level;
import org.sleuthkit.autopsy.coreutils.Logger;
import org.apache.solr.client.solrj.SolrServerException;
import org.sleuthkit.autopsy.corecomponents.OptionsPanel;
@ -97,35 +98,52 @@ class KeywordSearchConfigurationPanel2 extends javax.swing.JPanel implements Opt
timeRadioButton3 = new javax.swing.JRadioButton();
timeRadioButton4 = new javax.swing.JRadioButton();
skipNSRLCheckBox.setText(org.openide.util.NbBundle.getMessage(KeywordSearchConfigurationPanel2.class, "KeywordSearchConfigurationPanel2.skipNSRLCheckBox.text")); // NOI18N
skipNSRLCheckBox.setToolTipText(org.openide.util.NbBundle.getMessage(KeywordSearchConfigurationPanel2.class, "KeywordSearchConfigurationPanel2.skipNSRLCheckBox.toolTipText")); // NOI18N
skipNSRLCheckBox.setText(org.openide.util.NbBundle.getMessage(KeywordSearchConfigurationPanel2.class,
"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);
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.setToolTipText(org.openide.util.NbBundle.getMessage(KeywordSearchConfigurationPanel2.class, "KeywordSearchConfigurationPanel2.timeRadioButton1.toolTipText")); // NOI18N
timeRadioButton1.setText(org.openide.util.NbBundle.getMessage(KeywordSearchConfigurationPanel2.class,
"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.setToolTipText(org.openide.util.NbBundle.getMessage(KeywordSearchConfigurationPanel2.class, "KeywordSearchConfigurationPanel2.timeRadioButton2.toolTipText")); // NOI18N
timeRadioButton2.setText(org.openide.util.NbBundle.getMessage(KeywordSearchConfigurationPanel2.class,
"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.setToolTipText(org.openide.util.NbBundle.getMessage(KeywordSearchConfigurationPanel2.class, "KeywordSearchConfigurationPanel2.timeRadioButton3.toolTipText")); // NOI18N
timeRadioButton3.setText(org.openide.util.NbBundle.getMessage(KeywordSearchConfigurationPanel2.class,
"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.setToolTipText(org.openide.util.NbBundle.getMessage(KeywordSearchConfigurationPanel2.class, "KeywordSearchConfigurationPanel2.timeRadioButton4.toolTipText")); // NOI18N
timeRadioButton4.setText(org.openide.util.NbBundle.getMessage(KeywordSearchConfigurationPanel2.class,
"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);
this.setLayout(layout);
@ -239,14 +257,11 @@ class KeywordSearchConfigurationPanel2 extends javax.swing.JPanel implements Opt
private UpdateFrequency getSelectedTimeValue() {
if (timeRadioButton1.isSelected()) {
return UpdateFrequency.FAST;
}
else if (timeRadioButton2.isSelected()) {
} else if (timeRadioButton2.isSelected()) {
return UpdateFrequency.AVG;
}
else if (timeRadioButton3.isSelected()) {
} else if (timeRadioButton3.isSelected()) {
return UpdateFrequency.SLOW;
}
else if (timeRadioButton4.isSelected()) {
} else if (timeRadioButton4.isSelected()) {
return UpdateFrequency.SLOWEST;
}
return UpdateFrequency.DEFAULT;
@ -282,7 +297,8 @@ class KeywordSearchConfigurationPanel2 extends javax.swing.JPanel implements Opt
int newFilesIndexed = ((Integer) newValue).intValue();
filesIndexedValue.setText(Integer.toString(newFilesIndexed));
try {
chunksValLabel.setText(Integer.toString(KeywordSearch.getServer().queryNumIndexedChunks()));
chunksValLabel
.setText(Integer.toString(KeywordSearch.getServer().queryNumIndexedChunks()));
} catch (KeywordSearchModuleException ex) {
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.List;
import java.util.Map;
import org.sleuthkit.autopsy.coreutils.Logger;
import javax.swing.JCheckBox;
import org.sleuthkit.autopsy.corecomponents.OptionsPanel;
import org.sleuthkit.autopsy.coreutils.StringExtract;
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 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 List<SCRIPT> toUpdate;
@ -97,9 +101,10 @@ class KeywordSearchConfigurationPanel3 extends javax.swing.JPanel implements Opt
sb.append(")");
return sb.toString();
}
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));
for (StringExtract.StringExtractUnicodeTable.SCRIPT s : supportedScripts) {
String text = getLangText(s);
@ -112,45 +117,49 @@ class KeywordSearchConfigurationPanel3 extends javax.swing.JPanel implements Opt
}
private void reloadScriptsCheckBoxes() {
boolean utf16 =
Boolean.parseBoolean(KeywordSearchSettings.getStringExtractOption(AbstractFileExtract.ExtractOptions.EXTRACT_UTF16.toString()));
boolean utf16 =
Boolean.parseBoolean(KeywordSearchSettings.getStringExtractOption(
AbstractFileExtract.ExtractOptions.EXTRACT_UTF16.toString()));
enableUTF16Checkbox.setSelected(utf16);
boolean utf8 =
Boolean.parseBoolean(KeywordSearchSettings.getStringExtractOption(AbstractFileExtract.ExtractOptions.EXTRACT_UTF8.toString()));
boolean utf8 =
Boolean.parseBoolean(KeywordSearchSettings.getStringExtractOption(
AbstractFileExtract.ExtractOptions.EXTRACT_UTF8.toString()));
enableUTF8Checkbox.setSelected(utf8);
final List<SCRIPT> serviceScripts = KeywordSearchSettings.getStringExtractScripts();
final int components = checkPanel.getComponentCount();
for (int i = 0; i < components; ++i) {
JCheckBox ch = (JCheckBox) checkPanel.getComponent(i);
StringExtract.StringExtractUnicodeTable.SCRIPT script = scripts.get(ch.getText());
ch.setSelected(serviceScripts.contains(script));
}
}
private void activateWidgets() {
reloadScriptsCheckBoxes();
boolean utf16 =
Boolean.parseBoolean(KeywordSearchSettings.getStringExtractOption(AbstractFileExtract.ExtractOptions.EXTRACT_UTF16.toString()));
boolean utf16 =
Boolean.parseBoolean(KeywordSearchSettings.getStringExtractOption(
AbstractFileExtract.ExtractOptions.EXTRACT_UTF16.toString()));
enableUTF16Checkbox.setSelected(utf16);
boolean utf8 =
Boolean.parseBoolean(KeywordSearchSettings.getStringExtractOption(AbstractFileExtract.ExtractOptions.EXTRACT_UTF8.toString()));
boolean utf8 =
Boolean.parseBoolean(KeywordSearchSettings.getStringExtractOption(
AbstractFileExtract.ExtractOptions.EXTRACT_UTF8.toString()));
enableUTF8Checkbox.setSelected(utf8);
final boolean extractEnabled = utf16 || utf8;
boolean ingestNotRunning = !IngestManager.getDefault().isIngestRunning()
&& ! IngestManager.getDefault().isModuleRunning(KeywordSearchIngestModule.getDefault());
&& !IngestManager.getDefault().isModuleRunning(KeywordSearchIngestModule.getDefault());
//enable / disable checboxes
activateScriptsCheckboxes(extractEnabled && ingestNotRunning);
enableUTF16Checkbox.setEnabled(ingestNotRunning);
@ -173,7 +182,9 @@ class KeywordSearchConfigurationPanel3 extends javax.swing.JPanel implements Opt
enableUTF16Checkbox = new javax.swing.JCheckBox();
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));
@ -182,31 +193,37 @@ class KeywordSearchConfigurationPanel3 extends javax.swing.JPanel implements Opt
javax.swing.GroupLayout checkPanelLayout = new javax.swing.GroupLayout(checkPanel);
checkPanel.setLayout(checkPanelLayout);
checkPanelLayout.setHorizontalGroup(
checkPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGap(0, 428, Short.MAX_VALUE)
checkPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGap(0, 428, Short.MAX_VALUE)
);
checkPanelLayout.setVerticalGroup(
checkPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGap(0, 395, Short.MAX_VALUE)
checkPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGap(0, 395, Short.MAX_VALUE)
);
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() {
public void actionPerformed(java.awt.event.ActionEvent 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() {
public void actionPerformed(java.awt.event.ActionEvent 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);
this.setLayout(layout);
@ -243,18 +260,20 @@ class KeywordSearchConfigurationPanel3 extends javax.swing.JPanel implements Opt
);
}// </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();
activateScriptsCheckboxes(selected || this.enableUTF16Checkbox.isSelected());
}//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();
activateScriptsCheckboxes(selected || this.enableUTF8Checkbox.isSelected());
}//GEN-LAST:event_enableUTF16CheckboxActionPerformed
@ -270,19 +289,19 @@ class KeywordSearchConfigurationPanel3 extends javax.swing.JPanel implements Opt
@Override
public void store() {
KeywordSearchSettings.setStringExtractOption(AbstractFileExtract.ExtractOptions.EXTRACT_UTF8.toString(),
Boolean.toString(enableUTF8Checkbox.isSelected()));
Boolean.toString(enableUTF8Checkbox.isSelected()));
KeywordSearchSettings.setStringExtractOption(AbstractFileExtract.ExtractOptions.EXTRACT_UTF16.toString(),
Boolean.toString(enableUTF16Checkbox.isSelected()));
if(toUpdate!=null) {
KeywordSearchSettings.setStringExtractScripts(toUpdate);
Boolean.toString(enableUTF16Checkbox.isSelected()));
if (toUpdate != null) {
KeywordSearchSettings.setStringExtractScripts(toUpdate);
}
}
@Override
public void load() {
activateWidgets();
}
}

View File

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

View File

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

View File

@ -36,9 +36,11 @@ import java.util.logging.Level;
import org.openide.util.NbBundle;
import org.sleuthkit.autopsy.coreutils.Logger;
import javax.swing.SwingUtilities;
import javax.swing.SwingWorker;
import javax.swing.Timer;
import org.apache.tika.Tika;
import org.netbeans.api.progress.aggregate.AggregateProgressFactory;
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
* on currently configured lists for ingest and writes results to blackboard
* Reports interesting events to Inbox and to viewers
*
* <p/>
* Registered as a module in layer.xml
*/
public final class KeywordSearchIngestModule extends IngestModuleAbstractFile {
@ -96,10 +98,13 @@ public final class KeywordSearchIngestModule extends IngestModuleAbstractFile {
int getTime() {
return time;
}
};
}
;
private static final Logger logger = Logger.getLogger(KeywordSearchIngestModule.class.getName());
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();
private static KeywordSearchIngestModule instance = null;
private IngestServices services;
@ -132,7 +137,7 @@ public final class KeywordSearchIngestModule extends IngestModuleAbstractFile {
private KeywordSearchIngestSimplePanel simpleConfigPanel;
private KeywordSearchConfigurationPanel advancedConfigPanel;
private Tika tikaFormatDetector;
private enum IngestStatus {
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_TEXTEXTRACT, ///< File was skipped because of text extraction issues
SKIPPED_ERROR_IO ///< File was skipped because of IO issues reading it
};
}
;
private Map<Long, IngestStatus> ingestStatus;
//private constructor to ensure singleton instance
@ -175,9 +182,10 @@ public final class KeywordSearchIngestModule extends IngestModuleAbstractFile {
curDataSourceIds.add(fileSourceId);
} 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)) {
//skip indexing of virtual dirs (no content, no real name) - will index children files
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
ingestStatus.put(abstractFile.getId(), IngestStatus.SKIPPED_ERROR_IO);
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
indexer.indexFile(abstractFile, false);
return ProcessResult.OK;
}
processedFiles = true;
processedFiles = true;
//check if it's time to commit after previous processing
checkRunCommitSearch();
@ -337,7 +344,6 @@ public final class KeywordSearchIngestModule extends IngestModuleAbstractFile {
/**
* Initializes the module for new ingest run Sets up threads, timers,
* retrieves settings, keyword lists to run on
*
*/
@Override
public void init(IngestModuleInit initContext) {
@ -356,7 +362,8 @@ public final class KeywordSearchIngestModule extends IngestModuleAbstractFile {
if (!server.isRunning()) {
String msg = NbBundle.getMessage(this.getClass(), "KeywordSearchIngestModule.init.badInitMsg");
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));
return;
@ -399,8 +406,11 @@ public final class KeywordSearchIngestModule extends IngestModuleAbstractFile {
initKeywords();
if (keywords.isEmpty() || keywordLists.isEmpty()) {
services.postMessage(IngestMessage.createWarningMessage(++messageID, instance, NbBundle.getMessage(this.getClass(), "KeywordSearchIngestModule.init.noKwInLstMsg"),
NbBundle.getMessage(this.getClass(), "KeywordSearchIngestModule.init.onlyIdxKwSkipMsg")));
services.postMessage(IngestMessage.createWarningMessage(++messageID, instance,
NbBundle.getMessage(this.getClass(),
"KeywordSearchIngestModule.init.noKwInLstMsg"),
NbBundle.getMessage(this.getClass(),
"KeywordSearchIngestModule.init.onlyIdxKwSkipMsg")));
}
processedFiles = false;
@ -439,14 +449,13 @@ public final class KeywordSearchIngestModule extends IngestModuleAbstractFile {
@Override
public javax.swing.JPanel getSimpleConfiguration(String context) {
KeywordSearchListsXML.getCurrent().reload();
if (null == simpleConfigPanel) {
simpleConfigPanel = new KeywordSearchIngestSimplePanel();
}
else {
simpleConfigPanel = new KeywordSearchIngestSimplePanel();
} else {
simpleConfigPanel.load();
}
return simpleConfigPanel;
}
@ -455,7 +464,7 @@ public final class KeywordSearchIngestModule extends IngestModuleAbstractFile {
if (advancedConfigPanel == null) {
advancedConfigPanel = new KeywordSearchConfigurationPanel();
}
advancedConfigPanel.load();
return advancedConfigPanel;
}
@ -465,7 +474,7 @@ public final class KeywordSearchIngestModule extends IngestModuleAbstractFile {
if (advancedConfigPanel != null) {
advancedConfigPanel.store();
}
if (simpleConfigPanel != null) {
simpleConfigPanel.load();
}
@ -543,23 +552,42 @@ public final class KeywordSearchIngestModule extends IngestModuleAbstractFile {
}
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("<tr><td>").append(NbBundle.getMessage(this.getClass(), "KeywordSearchIngestModule.postIndexSummary.fileGenStringsHead")).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 border=0><tr><td>")
.append(NbBundle.getMessage(this.getClass(), "KeywordSearchIngestModule.postIndexSummary.knowFileHeaderLbl"))
.append("</td><td>").append(text_ingested).append("</td></tr>");
msg.append("<tr><td>").append(NbBundle.getMessage(this.getClass(),
"KeywordSearchIngestModule.postIndexSummary.fileGenStringsHead"))
.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>");
String indexStats = msg.toString();
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) {
MessageNotifyUtil.Notify.error(NbBundle.getMessage(this.getClass(), "KeywordSearchIngestModule.postIndexSummary.kwIdxErrsTitle"),
NbBundle.getMessage(this.getClass(), "KeywordSearchIngestModule.postIndexSummary.kwIdxErrMsgFiles", error_index));
}
else if (error_io + error_text > 0) {
MessageNotifyUtil.Notify.warn(NbBundle.getMessage(this.getClass(), "KeywordSearchIngestModule.postIndexSummary.kwIdxWarnMsgTitle"),
NbBundle.getMessage(this.getClass(), "KeywordSearchIngestModule.postIndexSummary.idxErrReadFilesMsg"));
MessageNotifyUtil.Notify.error(NbBundle.getMessage(this.getClass(),
"KeywordSearchIngestModule.postIndexSummary.kwIdxErrsTitle"),
NbBundle.getMessage(this.getClass(),
"KeywordSearchIngestModule.postIndexSummary.kwIdxErrMsgFiles",
error_index));
} 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
* chunks
*
* @param aFile file to extract strings from, divide into chunks and
* index
* @param aFile file to extract strings from, divide into chunks and
* index
* @param detectedFormat mime-type detected, or null if none detected
* @return true if the file was text_ingested, false otherwise
* @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.
*
* @param aFile file to extract strings from, divide into chunks and
* index
* index
* @return true if the file was text_ingested, false otherwise
*/
private boolean extractStringsAndIndex(AbstractFile aFile) {
@ -737,12 +765,16 @@ public final class KeywordSearchIngestModule extends IngestModuleAbstractFile {
ingestStatus.put(aFile.getId(), IngestStatus.STRINGS_INGESTED);
return true;
} 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);
return false;
}
} 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);
return false;
}
@ -752,9 +784,9 @@ public final class KeywordSearchIngestModule extends IngestModuleAbstractFile {
* Check with every extractor if it supports the file with the detected
* format
*
* @param aFile file to check for
* @param aFile file to check for
* @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
*/
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.
*
* @param aFile File to analyze
* @param aFile File to analyze
* @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) {
//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.
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);
}
@ -790,8 +823,7 @@ public final class KeywordSearchIngestModule extends IngestModuleAbstractFile {
try {
ingester.ingest(aFile, false); //meta-data only
ingestStatus.put(aFile.getId(), IngestStatus.METADATA_INGESTED);
}
catch (IngesterException ex) {
} catch (IngesterException ex) {
ingestStatus.put(aFile.getId(), IngestStatus.SKIPPED_ERROR_INDEXING);
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 {
is = new ReadContentInputStream(aFile);
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);
}
finally {
} finally {
if (is != null) {
try {
is.close();
@ -818,9 +848,9 @@ public final class KeywordSearchIngestModule extends IngestModuleAbstractFile {
}
}
}
// @@@ Add file type signature to blackboard here
//logger.log(Level.INFO, "Detected format: " + aFile.getName() + " " + detectedFormat);
// we skip archive formats that are opened by the archive module.
@ -829,8 +859,7 @@ public final class KeywordSearchIngestModule extends IngestModuleAbstractFile {
try {
ingester.ingest(aFile, false); //meta-data only
ingestStatus.put(aFile.getId(), IngestStatus.METADATA_INGESTED);
}
catch (IngesterException ex) {
} catch (IngesterException ex) {
ingestStatus.put(aFile.getId(), IngestStatus.SKIPPED_ERROR_INDEXING);
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 {
//logger.log(Level.INFO, "indexing: " + aFile.getName());
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);
} else {
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");
}
final String displayName = NbBundle.getMessage(this.getClass(), "KeywordSearchIngestModule.doInBackGround.displayName") +
(finalRun ? (" - "+ NbBundle.getMessage(this.getClass(), "KeywordSearchIngestModule.doInBackGround.finalizeMsg")) : "");
progressGroup = AggregateProgressFactory.createSystemHandle(displayName + (" ("+
NbBundle.getMessage(this.getClass(), "KeywordSearchIngestModule.doInBackGround.pendingMsg") +")"), null, new Cancellable() {
final String displayName =
NbBundle.getMessage(this.getClass(), "KeywordSearchIngestModule.doInBackGround.displayName") +
(finalRun ? (" - " + NbBundle.getMessage(this.getClass(),
"KeywordSearchIngestModule.doInBackGround.finalizeMsg"))
: "");
progressGroup = AggregateProgressFactory.createSystemHandle(displayName + (" (" +
NbBundle.getMessage(this.getClass(), "KeywordSearchIngestModule.doInBackGround.pendingMsg") + ")"),
null, new Cancellable() {
@Override
public boolean cancel() {
logger.log(Level.INFO, "Cancelling the searcher by user.");
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);
}
@ -954,7 +991,8 @@ public final class KeywordSearchIngestModule extends IngestModuleAbstractFile {
for (Keyword keywordQuery : keywords) {
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;
}
@ -974,15 +1012,15 @@ public final class KeywordSearchIngestModule extends IngestModuleAbstractFile {
boolean isRegex = !keywordQuery.isLiteral();
if (isRegex) {
del = new TermComponentQuery(keywordQuery);
}
else {
} else {
del = new LuceneQuery(keywordQuery);
del.escape();
del.escape();
}
//limit search to currently ingested data sources
//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);
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
return null;
} 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;
} catch (Exception 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()) {
//checking for cancellation between results
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;
}
// update progress display
String hitDisplayStr = hitTerm.getQuery();
if (hitDisplayStr.length() > 50) {
@ -1042,15 +1082,17 @@ public final class KeywordSearchIngestModule extends IngestModuleAbstractFile {
//subProgresses[keywordsSearched].progress(unitProgress);
// 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()) {
// get the snippet for the first hit in the file
String snippet = null;
final String snippetQuery = KeywordSearchUtil.escapeLuceneQuery(hitTerm.getQuery());
int chunkId = contentHitsFlattened.get(hitFile);
try {
snippet = LuceneQuery.querySnippet(snippetQuery, hitFile.getId(), chunkId, isRegex, true);
snippet = LuceneQuery
.querySnippet(snippetQuery, hitFile.getId(), chunkId, isRegex, true);
} catch (NoOpenCoreException e) {
logger.log(Level.WARNING, "Error querying snippet: " + snippetQuery, e);
//no reason to continue
@ -1061,9 +1103,12 @@ public final class KeywordSearchIngestModule extends IngestModuleAbstractFile {
}
// 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) {
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;
}
@ -1076,13 +1121,16 @@ public final class KeywordSearchIngestModule extends IngestModuleAbstractFile {
//final int hitFiles = newResults.size();
if (!keywordQuery.isLiteral()) {
subjectSb.append(NbBundle.getMessage(this.getClass(), "KeywordSearchIngestModule.regExpHitLbl"));
subjectSb.append(NbBundle.getMessage(this.getClass(),
"KeywordSearchIngestModule.regExpHitLbl"));
} else {
subjectSb.append(NbBundle.getMessage(this.getClass(), "KeywordSearchIngestModule.kwHitLbl"));
subjectSb.append(NbBundle.getMessage(this.getClass(),
"KeywordSearchIngestModule.kwHitLbl"));
}
//subjectSb.append("<");
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) {
final String keyword = attr.getValueString();
subjectSb.append(keyword);
@ -1096,49 +1144,64 @@ public final class KeywordSearchIngestModule extends IngestModuleAbstractFile {
detailsSb.append("<table border='0' cellpadding='4' width='280'>");
//hit
detailsSb.append("<tr>");
detailsSb.append(NbBundle.getMessage(this.getClass(), "KeywordSearchIngestModule.kwHitLThLbl"));
detailsSb.append("<td>").append(EscapeUtil.escapeHtml(attr.getValueString())).append("</td>");
detailsSb.append(NbBundle.getMessage(this.getClass(),
"KeywordSearchIngestModule.kwHitLThLbl"));
detailsSb.append("<td>").append(EscapeUtil.escapeHtml(attr.getValueString()))
.append("</td>");
detailsSb.append("</tr>");
//preview
attr = written.getAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_KEYWORD_PREVIEW.getTypeID());
attr = written.getAttribute(
BlackboardAttribute.ATTRIBUTE_TYPE.TSK_KEYWORD_PREVIEW.getTypeID());
if (attr != null) {
detailsSb.append("<tr>");
detailsSb.append(NbBundle.getMessage(this.getClass(), "KeywordSearchIngestModule.previewThLbl"));
detailsSb.append("<td>").append(EscapeUtil.escapeHtml(attr.getValueString())).append("</td>");
detailsSb.append(NbBundle.getMessage(this.getClass(),
"KeywordSearchIngestModule.previewThLbl"));
detailsSb.append("<td>").append(EscapeUtil.escapeHtml(attr.getValueString()))
.append("</td>");
detailsSb.append("</tr>");
}
//file
detailsSb.append("<tr>");
detailsSb.append(NbBundle.getMessage(this.getClass(), "KeywordSearchIngestModule.fileThLbl"));
detailsSb.append("<td>").append(hitFile.getParentPath()).append(hitFile.getName()).append("</td>");
detailsSb.append(NbBundle.getMessage(this.getClass(),
"KeywordSearchIngestModule.fileThLbl"));
detailsSb.append("<td>").append(hitFile.getParentPath()).append(hitFile.getName())
.append("</td>");
detailsSb.append("</tr>");
//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(NbBundle.getMessage(this.getClass(), "KeywordSearchIngestModule.listThLbl"));
detailsSb.append(NbBundle.getMessage(this.getClass(),
"KeywordSearchIngestModule.listThLbl"));
detailsSb.append("<td>").append(attr.getValueString()).append("</td>");
detailsSb.append("</tr>");
//regex
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) {
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("</tr>");
}
}
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
@ -1148,7 +1211,8 @@ public final class KeywordSearchIngestModule extends IngestModuleAbstractFile {
//update artifact browser
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
@ -1198,6 +1262,7 @@ public final class KeywordSearchIngestModule extends IngestModuleAbstractFile {
//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
//NEED to call this method always right before doInBackground() returns
/**
* Performs the cleanup that needs to be done right AFTER
* 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
//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>>();
for (String termResult : queryResult.keySet()) {

View File

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

View File

@ -26,6 +26,7 @@ import java.util.Date;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import org.sleuthkit.autopsy.coreutils.Logger;
import org.sleuthkit.autopsy.coreutils.PlatformUtil;
import org.sleuthkit.datamodel.BlackboardAttribute;
@ -53,13 +54,15 @@ public abstract class KeywordSearchListsAbstract {
/**
* Property change event support
* In events: For all of these enums, the old value should be null, and
* the new value should be the keyword list name string.
* In events: For all of these enums, the old value should be null, and
* the new value should be the keyword list name string.
*/
public enum ListsEvt {
LIST_ADDED, LIST_DELETED, LIST_UPDATED
};
}
;
/**
* get instance for managing the current keyword list of the application
@ -77,41 +80,47 @@ public abstract class KeywordSearchListsAbstract {
}
private void prepopulateLists() {
if (! theLists.isEmpty()) {
if (!theLists.isEmpty()) {
return;
}
//phone number
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));
//IP address
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
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
List<Keyword> urls = new ArrayList<Keyword>();
//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));
//disable messages for harcoded/locked lists
String name;
name = "Phone Numbers";
lockedLists.add(name);
addList(name, phones, false, false, true);
name = "IP Addresses";
lockedLists.add(name);
addList(name, ips, false, false, true);
name = "Email Addresses";
lockedLists.add(name);
addList(name, emails, true, false, true);
name = "URLs";
lockedLists.add(name);
addList(name, urls, false, false, true);
@ -126,7 +135,7 @@ public abstract class KeywordSearchListsAbstract {
//theLists.clear();
//populate only the first time
prepopulateLists();
//reset all the lists other than locked lists (we don't save them to XML)
//we want to preserve state of locked lists
List<String> toClear = new ArrayList<String>();
@ -137,8 +146,8 @@ public abstract class KeywordSearchListsAbstract {
}
for (String clearList : toClear) {
theLists.remove(clearList);
}
}
if (!this.listFileExists()) {
//create new if it doesn't exist
save();
@ -283,8 +292,8 @@ public abstract class KeywordSearchListsAbstract {
* adds the new word list using name id replacing old one if exists with the
* same name
*
* @param name the name of the new list or list to replace
* @param newList list of keywords
* @param name the name of the new list or list to replace
* @param newList list of keywords
* @param useForIngest should this list be used for ingest
* @return true if old list was replaced
*/
@ -300,14 +309,15 @@ public abstract class KeywordSearchListsAbstract {
// }
changeSupport.firePropertyChange(ListsEvt.LIST_ADDED.toString(), null, name);
} 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) {
// save();
// }
replaced = true;
changeSupport.firePropertyChange(ListsEvt.LIST_UPDATED.toString(), null, name);
}
return replaced;
}
@ -323,7 +333,8 @@ public abstract class KeywordSearchListsAbstract {
}
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();
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) {
changeSupport.firePropertyChange(ListsEvt.LIST_UPDATED.toString(), null, over.getName());
@ -403,7 +414,7 @@ public abstract class KeywordSearchListsAbstract {
//deleted = save();
}
changeSupport.firePropertyChange(ListsEvt.LIST_DELETED.toString(), null, name);
return true;
}
@ -412,11 +423,12 @@ public abstract class KeywordSearchListsAbstract {
* writes out current list replacing the last lists file
*/
public abstract boolean save();
/**
* writes out current list replacing the last lists file
*
* @param isExport true is this save operation is an export and not a 'Save
* As'
* As'
*/
public abstract boolean save(boolean isExport);
@ -429,11 +441,11 @@ public abstract class KeywordSearchListsAbstract {
File f = new File(filePath);
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);
}
/**
* a representation of a single keyword list created or loaded
*/
@ -447,7 +459,8 @@ public abstract class KeywordSearchListsAbstract {
private List<Keyword> keywords;
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.created = created;
this.modified = modified;
@ -457,7 +470,8 @@ public abstract class KeywordSearchListsAbstract {
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);
}

View File

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

View File

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

View File

@ -163,31 +163,38 @@ class KeywordSearchListsViewerPanel extends AbstractKeywordSearchPerformer {
private void initIngest(boolean running) {
if (running) {
ingestRunning = true;
searchAddButton.setText(NbBundle.getMessage(this.getClass(), "KeywordSearchListsViewerPanel.initIngest.addIngestTitle"));
searchAddButton.setToolTipText(NbBundle.getMessage(this.getClass(), "KeywordSearchListsViewerPanel.initIngest.addIngestMsg" ));
searchAddButton.setText(
NbBundle.getMessage(this.getClass(), "KeywordSearchListsViewerPanel.initIngest.addIngestTitle"));
searchAddButton.setToolTipText(
NbBundle.getMessage(this.getClass(), "KeywordSearchListsViewerPanel.initIngest.addIngestMsg"));
listsTableModel.resync();
} else {
ingestRunning = false;
searchAddButton.setText(NbBundle.getMessage(this.getClass(), "KeywordSearchListsViewerPanel.initIngest.searchIngestTitle"));
searchAddButton.setToolTipText(NbBundle.getMessage(this.getClass(), "KeywordSearchListsViewerPanel.initIngest.addIdxSearchMsg"));
searchAddButton.setText(
NbBundle.getMessage(this.getClass(), "KeywordSearchListsViewerPanel.initIngest.searchIngestTitle"));
searchAddButton.setToolTipText(
NbBundle.getMessage(this.getClass(), "KeywordSearchListsViewerPanel.initIngest.addIdxSearchMsg"));
listsTableModel.resync();
}
updateIngestIndexLabel(running);
}
private void updateIngestIndexLabel(boolean ingestRunning) {
if (ingestRunning) {
ingestIndexLabel.setText(NbBundle.getMessage(this.getClass(), "KeywordSearchListsViewerPanel.initIngest.ongoingIngestMsg", filesIndexed));
}
else {
ingestIndexLabel.setText(NbBundle.getMessage(this.getClass(), "KeywordSearchListsViewerPanel.initIngest.fileIndexCtMsg", filesIndexed));
ingestIndexLabel.setText(
NbBundle.getMessage(this.getClass(), "KeywordSearchListsViewerPanel.initIngest.ongoingIngestMsg",
filesIndexed));
} else {
ingestIndexLabel.setText(
NbBundle.getMessage(this.getClass(), "KeywordSearchListsViewerPanel.initIngest.fileIndexCtMsg",
filesIndexed));
}
}
@Override
protected void postFilesIndexedChange() {
updateIngestIndexLabel(ingestRunning);
updateIngestIndexLabel(ingestRunning);
}
/**
@ -234,18 +241,22 @@ class KeywordSearchListsViewerPanel extends AbstractKeywordSearchPerformer {
jSplitPane1.setRightComponent(rightPane);
manageListsButton.setText(org.openide.util.NbBundle.getMessage(KeywordSearchListsViewerPanel.class, "KeywordSearchListsViewerPanel.manageListsButton.text")); // NOI18N
manageListsButton.setToolTipText(org.openide.util.NbBundle.getMessage(KeywordSearchListsViewerPanel.class, "KeywordSearchListsViewerPanel.manageListsButton.toolTipText")); // NOI18N
manageListsButton.setText(org.openide.util.NbBundle.getMessage(KeywordSearchListsViewerPanel.class,
"KeywordSearchListsViewerPanel.manageListsButton.text")); // NOI18N
manageListsButton.setToolTipText(org.openide.util.NbBundle.getMessage(KeywordSearchListsViewerPanel.class,
"KeywordSearchListsViewerPanel.manageListsButton.toolTipText")); // NOI18N
manageListsButton.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent 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.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);
this.setLayout(layout);
@ -278,9 +289,11 @@ class KeywordSearchListsViewerPanel extends AbstractKeywordSearchPerformer {
);
}// </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();
}//GEN-LAST:event_manageListsButtonActionPerformed
// Variables declaration - do not modify//GEN-BEGIN:variables
private javax.swing.JLabel ingestIndexLabel;
private javax.swing.JSplitPane jSplitPane1;
@ -440,7 +453,8 @@ class KeywordSearchListsViewerPanel extends AbstractKeywordSearchPerformer {
}
List<KeywordSearchListsAbstract.KeywordSearchList> getSelectedListsL() {
List<KeywordSearchListsAbstract.KeywordSearchList> ret = new ArrayList<KeywordSearchListsAbstract.KeywordSearchList>();
List<KeywordSearchListsAbstract.KeywordSearchList> ret
= new ArrayList<KeywordSearchListsAbstract.KeywordSearchList>();
for (String s : getSelectedLists()) {
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.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import org.sleuthkit.autopsy.coreutils.Logger;
import org.sleuthkit.autopsy.coreutils.XMLUtil;
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
* 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 LIST_EL = "keyword_list";
@ -57,23 +58,23 @@ public class KeywordSearchListsXML extends KeywordSearchListsAbstract{
private static final Logger logger = Logger.getLogger(KeywordSearchListsXML.class.getName());
private DateFormat dateFormatter;
/**
* Constructor to obtain handle on other that the current keyword list
* (such as for import or export)
*
* @param xmlFile xmlFile to obtain KeywordSearchListsXML handle on
*/
KeywordSearchListsXML(String xmlFile) {
super(xmlFile);
dateFormatter = new SimpleDateFormat(DATE_FORMAT);
}
@Override
public boolean save() {
return save(false);
}
@Override
public boolean save(boolean isExport) {
boolean success = false;
@ -102,7 +103,7 @@ public class KeywordSearchListsXML extends KeywordSearchListsAbstract{
listEl.setAttribute(LIST_NAME_ATTR, listName);
listEl.setAttribute(LIST_CREATE_ATTR, created);
listEl.setAttribute(LIST_MOD_ATTR, modified);
// only write the 'useForIngest' and 'ingestMessages' attributes
// if we're not exporting the list
if (!isExport) {
@ -112,7 +113,7 @@ public class KeywordSearchListsXML extends KeywordSearchListsAbstract{
for (Keyword keyword : keywords) {
Element keywordEl = doc.createElement(KEYWORD_EL);
String literal = keyword.isLiteral()?"true":"false";
String literal = keyword.isLiteral() ? "true" : "false";
keywordEl.setAttribute(KEYWORD_LITERAL_ATTR, literal);
BlackboardAttribute.ATTRIBUTE_TYPE selectorType = keyword.getType();
if (selectorType != null) {
@ -154,30 +155,29 @@ public class KeywordSearchListsXML extends KeywordSearchListsAbstract{
final String name = listEl.getAttribute(LIST_NAME_ATTR);
final String created = listEl.getAttribute(LIST_CREATE_ATTR);
final String modified = listEl.getAttribute(LIST_MOD_ATTR);
//set these bools to true by default, if they don't exist in XML
Boolean useForIngestBool;
Boolean ingestMessagesBool;
if (listEl.hasAttribute(LIST_USE_FOR_INGEST) ) {
Boolean ingestMessagesBool;
if (listEl.hasAttribute(LIST_USE_FOR_INGEST)) {
useForIngestBool = Boolean.parseBoolean(listEl.getAttribute(LIST_USE_FOR_INGEST));
}
else {
} else {
useForIngestBool = true;
}
if (listEl.hasAttribute(LIST_INGEST_MSGS)) {
ingestMessagesBool = Boolean.parseBoolean(listEl.getAttribute(LIST_INGEST_MSGS));
}
else {
} else {
ingestMessagesBool = true;
}
Date createdDate = dateFormatter.parse(created);
Date modDate = dateFormatter.parse(modified);
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
NodeList wordsNList = listEl.getElementsByTagName(KEYWORD_EL);
@ -188,12 +188,13 @@ public class KeywordSearchListsXML extends KeywordSearchListsAbstract{
boolean isLiteral = literal.equals("true");
Keyword keyword = new Keyword(wordEl.getTextContent(), isLiteral);
String selector = wordEl.getAttribute(KEYWORD_SELECTOR_ATTR);
if (! selector.equals("")) {
BlackboardAttribute.ATTRIBUTE_TYPE selectorType = BlackboardAttribute.ATTRIBUTE_TYPE.fromLabel(selector);
if (!selector.equals("")) {
BlackboardAttribute.ATTRIBUTE_TYPE selectorType = BlackboardAttribute.ATTRIBUTE_TYPE
.fromLabel(selector);
keyword.setType(selectorType);
}
words.add(keyword);
}
theLists.put(name, list);
}

View File

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

View File

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

View File

@ -34,20 +34,23 @@ import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.util.List;
import java.util.logging.Level;
import org.sleuthkit.autopsy.coreutils.Logger;
import javax.swing.JMenuItem;
import javax.swing.SwingUtilities;
import javax.swing.event.PopupMenuEvent;
import javax.swing.event.PopupMenuListener;
import org.apache.solr.client.solrj.SolrServerException;
import org.sleuthkit.autopsy.casemodule.Case;
/**
* Keyword search toolbar (in upper right, by default) which allows to search for single terms or phrases
*
* 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.
* The default, Tahoma 14, could not perform this task at the desired size, and neither could numerous other fonts.
* <p/>
* 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.
* The default, Tahoma 14, could not perform this task at the desired size, and neither could numerous other fonts.
*/
class KeywordSearchPanel extends AbstractKeywordSearchPerformer {
@ -57,7 +60,9 @@ class KeywordSearchPanel extends AbstractKeywordSearchPerformer {
private boolean entered = false;
private static KeywordSearchPanel instance;
/** Creates new form KeywordSearchPanel */
/**
* Creates new form KeywordSearchPanel
*/
private KeywordSearchPanel() {
initComponents();
customizeComponents();
@ -78,8 +83,7 @@ class KeywordSearchPanel extends AbstractKeywordSearchPerformer {
//nothing to update
}
private void customizeComponents() {
listener = new KeywordPropertyChangeListener();
@ -172,7 +176,8 @@ class KeywordSearchPanel extends AbstractKeywordSearchPerformer {
entered = false;
}
/** This method is called from within the constructor to
/**
* This method is called from within the constructor to
* initialize the form.
* WARNING: Do NOT modify this code. The content of this method is
* always regenerated by the Form Editor.
@ -195,19 +200,24 @@ class KeywordSearchPanel extends AbstractKeywordSearchPerformer {
searchButton = new javax.swing.JLabel();
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);
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);
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);
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);
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);
setOpaque(false);
@ -217,7 +227,8 @@ class KeywordSearchPanel extends AbstractKeywordSearchPerformer {
searchBox.setFont(new java.awt.Font("Monospaced", 0, 14)); // NOI18N
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.setEnabled(false);
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.setText(org.openide.util.NbBundle.getMessage(KeywordSearchPanel.class, "KeywordSearchPanel.settingsLabel.text")); // NOI18N
settingsLabel.setIcon(new javax.swing.ImageIcon(
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.setEnabled(false);
settingsLabel.setMaximumSize(new java.awt.Dimension(23, 20));
@ -237,16 +250,20 @@ class KeywordSearchPanel extends AbstractKeywordSearchPerformer {
public void mouseEntered(java.awt.event.MouseEvent evt) {
settingsLabelMouseEntered(evt);
}
public void mouseExited(java.awt.event.MouseEvent evt) {
settingsLabelMouseExited(evt);
}
public void mousePressed(java.awt.event.MouseEvent evt) {
settingsLabelMousePressed(evt);
}
});
searchButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/org/sleuthkit/autopsy/keywordsearch/search-icon.png"))); // NOI18N
searchButton.setText(org.openide.util.NbBundle.getMessage(KeywordSearchPanel.class, "KeywordSearchPanel.searchButton.text")); // NOI18N
searchButton.setIcon(new javax.swing.ImageIcon(
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.setEnabled(false);
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)
);
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.setBorderPainted(false);
listsButton.setContentAreaFilled(false);
listsButton.setEnabled(false);
listsButton.setRolloverIcon(new javax.swing.ImageIcon(getClass().getResource("/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.setRolloverIcon(new javax.swing.ImageIcon(getClass().getResource(
"/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() {
public void mousePressed(java.awt.event.MouseEvent evt) {
listsButtonMousePressed(evt);
@ -297,17 +317,21 @@ class KeywordSearchPanel extends AbstractKeywordSearchPerformer {
javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
this.setLayout(layout);
layout.setHorizontalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup()
.addComponent(listsButton)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, 18, Short.MAX_VALUE)
.addComponent(searchBoxPanel, javax.swing.GroupLayout.PREFERRED_SIZE, 244, javax.swing.GroupLayout.PREFERRED_SIZE)
.addContainerGap())
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup()
.addComponent(listsButton)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, 18,
Short.MAX_VALUE)
.addComponent(searchBoxPanel, javax.swing.GroupLayout.PREFERRED_SIZE, 244,
javax.swing.GroupLayout.PREFERRED_SIZE)
.addContainerGap())
);
layout.setVerticalGroup(
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(searchBoxPanel, javax.swing.GroupLayout.DEFAULT_SIZE, 27, Short.MAX_VALUE)
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(searchBoxPanel, javax.swing.GroupLayout.DEFAULT_SIZE, 27, Short.MAX_VALUE)
);
}// </editor-fold>//GEN-END:initComponents
@ -331,7 +355,8 @@ class KeywordSearchPanel extends AbstractKeywordSearchPerformer {
maybeShowListsPopup(evt);
}//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:
}//GEN-LAST:event_listsButtonActionPerformed
@ -340,12 +365,15 @@ class KeywordSearchPanel extends AbstractKeywordSearchPerformer {
}//GEN-LAST:event_searchButtonMousePressed
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
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
// Variables declaration - do not modify//GEN-BEGIN:variables
private javax.swing.JMenuItem copyMenuItem;
private javax.swing.JMenuItem cutMenuItem;
@ -405,11 +433,9 @@ class KeywordSearchPanel extends AbstractKeywordSearchPerformer {
final int numIndexedFiles = KeywordSearch.getServer().queryNumIndexedFiles();
KeywordSearch.fireNumIndexedFilesChange(null, new Integer(numIndexedFiles));
//setFilesIndexed(numIndexedFiles);
}
catch (NoOpenCoreException ex) {
} catch (NoOpenCoreException 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());
}
break;

View File

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

View File

@ -21,92 +21,99 @@ package org.sleuthkit.autopsy.keywordsearch;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import org.apache.solr.client.solrj.response.TermsResponse.Term;
import org.sleuthkit.datamodel.AbstractFile;
/**
* Interface for a search query. Implemented by various
* engines or methods of using the same engine. One of these
* is created for each query.
* is created for each query.
*/
interface KeywordSearchQuery {
/**
* validate the query pre execution
*
* @return true if the query passed validation
*/
public boolean validate();
/**
* execute query and return results without publishing them
* return results for all matching terms
*
* @return
* @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
* Adding multiple filters ANDs them together.
* For OR, add multiple ids to a single filter
*
* @param filter filter to set on the query
*/
public void addFilter(KeywordQueryFilter filter);
/**
* Set an optional SOLR field to narrow down the search
*
* @param field field to set on the query
*/
public void setField(String field);
/**
* escape the query string and use the escaped string in the query
*/
public void escape();
/**
*
* @return true if query was escaped
*/
public boolean isEscaped();
/**
*
* @return true if query is a literal query (non regex)
*/
public boolean isLiteral();
/**
* return original keyword/query string
*
* @return the query String supplied originally
*/
public String getQueryString();
/**
* return escaped keyword/query string if escaping was done
*
* @return the escaped query string, or original string if no escaping done
*/
public String getEscapedQueryString();
/**
* get terms associated with the query if any
*
* @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
* 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 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
* @return collection of results (with cached bb artifacts/attributes) created and written
*/
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
* the results.
* the results.
*/
class KeywordSearchQueryManager {
// how to display the results
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.
DETAIL // not currently used, but seems like it has three levels of nodes
};
private List<Keyword> keywords;
private Presentation presentation;
private List<KeywordSearchQuery> queryDelegates;
@ -55,8 +56,7 @@ class KeywordSearchQueryManager {
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
*/
public KeywordSearchQueryManager(List<Keyword> queries, Presentation presentation) {
@ -67,9 +67,8 @@ class KeywordSearchQueryManager {
}
/**
*
* @param query Keyword to search for
* @param qt Query type
* @param query Keyword to search for
* @param qt Query type
* @param presentation Presentation Layout
*/
public KeywordSearchQueryManager(String query, QueryType qt, Presentation presentation) {
@ -81,9 +80,8 @@ class KeywordSearchQueryManager {
}
/**
*
* @param query Keyword to search for
* @param isLiteral false if reg-exp
* @param query Keyword to search for
* @param isLiteral false if reg-exp
* @param presentation Presentation layout
*/
public KeywordSearchQueryManager(String query, boolean isLiteral, Presentation presentation) {
@ -138,7 +136,7 @@ class KeywordSearchQueryManager {
// q.execute();
// }
// } else {
//Collapsed view
Collection<KeyValueQuery> things = new ArrayList<>();
int queryID = 0;
@ -154,11 +152,14 @@ class KeywordSearchQueryManager {
String queryConcatStr = queryConcat.toString();
final int queryConcatStrLen = queryConcatStr.length();
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);
if (things.size() > 0) {
Children childThingNodes =
Children.create(new KeywordSearchResultFactory(keywords, things, presentation, searchResultWin), true);
Children.create(new KeywordSearchResultFactory(keywords, things, presentation, searchResultWin),
true);
rootNode = new AbstractNode(childThingNodes);
} else {
@ -175,6 +176,7 @@ class KeywordSearchQueryManager {
/**
* validate the queries before they are run
*
* @return false if any are invalid
*/
public boolean validate() {

View File

@ -27,9 +27,12 @@ import java.util.List;
import java.util.Map;
import java.util.concurrent.locks.ReentrantReadWriteLock;
import java.util.logging.Level;
import org.sleuthkit.autopsy.coreutils.Logger;
import javax.swing.SwingUtilities;
import javax.swing.SwingWorker;
import org.netbeans.api.progress.ProgressHandle;
import org.netbeans.api.progress.ProgressHandleFactory;
import org.openide.nodes.ChildFactory;
@ -54,7 +57,6 @@ import org.sleuthkit.datamodel.FsContent;
import org.sleuthkit.datamodel.TskData.TSK_DB_FILES_TYPE_ENUM;
/**
*
* factory produces top level nodes with query
* responsible for assembling nodes and columns in the right way
* and performing lazy queries as needed
@ -66,41 +68,41 @@ class KeywordSearchResultFactory extends ChildFactory<KeyValueQuery> {
public static enum CommonPropertyTypes {
KEYWORD {
@Override
public String toString() {
return BlackboardAttribute.ATTRIBUTE_TYPE.TSK_KEYWORD.getDisplayName();
}
},
REGEX {
@Override
public String toString() {
return BlackboardAttribute.ATTRIBUTE_TYPE.TSK_KEYWORD_REGEXP.getDisplayName();
}
},
CONTEXT {
@Override
public String toString() {
return BlackboardAttribute.ATTRIBUTE_TYPE.TSK_KEYWORD_PREVIEW.getDisplayName();
}
},
}
private final Presentation presentation;
private List<Keyword> queries;
private Collection<KeyValueQuery> things;
private final DataResultTopComponent viewer; //viewer driving this child node factory
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.things = things;
this.presentation = presentation;
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.add(query);
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
* we need to preinitialize properties when sending parent Node)
*
* @param toSet property set map for a Node
*/
public static void initCommonProperties(Map<String, Object> toSet) {
@ -121,7 +124,8 @@ class KeywordSearchResultFactory extends ChildFactory<KeyValueQuery> {
toSet.put(commonTypes[i].toString(), "");
}
AbstractAbstractFileNode.AbstractFilePropertyType[] fsTypes = AbstractAbstractFileNode.AbstractFilePropertyType.values();
AbstractAbstractFileNode.AbstractFilePropertyType[] fsTypes = AbstractAbstractFileNode.AbstractFilePropertyType
.values();
final int FS_PROPS_LEN = fsTypes.length;
for (int i = 0; i < FS_PROPS_LEN; ++i) {
toSet.put(fsTypes[i].toString(), "");
@ -150,9 +154,8 @@ class KeywordSearchResultFactory extends ChildFactory<KeyValueQuery> {
setCommonProperty(map, CommonPropertyTypes.REGEX, Boolean.valueOf(!thing.getQuery().isEscaped()));
ResultCollapsedChildFactory childFactory = new ResultCollapsedChildFactory(thing);
childFactory.createKeysForFlatNodes(toPopulate);
}
}
else if (presentation == Presentation.DETAIL) {
}
} else if (presentation == Presentation.DETAIL) {
Iterator<KeyValueQuery> it = things.iterator();
for (Keyword keyword : queries) {
Map<String, Object> map = new LinkedHashMap<>();
@ -176,7 +179,7 @@ class KeywordSearchResultFactory extends ChildFactory<KeyValueQuery> {
toPopulate.add(thing);
}
}
return true;
}
@ -185,9 +188,8 @@ class KeywordSearchResultFactory extends ChildFactory<KeyValueQuery> {
ChildFactory<KeyValueQuery> childFactory;
if (presentation == Presentation.FLAT) {
ResultCollapsedChildFactory factory = new ResultCollapsedChildFactory(thing);
return factory.createFlatNodeForKey(thing);
}
else if (presentation == Presentation.COLLAPSE) {
return factory.createFlatNodeForKey(thing);
} else if (presentation == Presentation.COLLAPSE) {
childFactory = new ResultCollapsedChildFactory(thing);
final Node ret = new KeyValueNode(thing, Children.create(childFactory, true));
SwingUtilities.invokeLater(new Runnable() {
@ -224,7 +226,7 @@ class KeywordSearchResultFactory extends ChildFactory<KeyValueQuery> {
public boolean createKeysForFlatNodes(List<KeyValueQuery> toPopulate) {
return createKeys(toPopulate);
}
@Override
protected boolean createKeys(List<KeyValueQuery> toPopulate) {
final KeyValueQuery queryThingQuery = queryThing;
@ -236,7 +238,7 @@ class KeywordSearchResultFactory extends ChildFactory<KeyValueQuery> {
}
List<KeyValueQuery> tempList = new ArrayList<>();
//execute the query and get fscontents matching
Map<String, List<ContentHit>> tcqRes;
try {
@ -249,7 +251,8 @@ class KeywordSearchResultFactory extends ChildFactory<KeyValueQuery> {
//get listname
String listName = "";
KeywordSearchListsAbstract.KeywordSearchList list = KeywordSearchListsXML.getCurrent().getListWithKeyword(tcq.getQueryString());
KeywordSearchListsAbstract.KeywordSearchList list = KeywordSearchListsXML.getCurrent().getListWithKeyword(
tcq.getQueryString());
if (list != null) {
listName = list.getName();
}
@ -264,7 +267,7 @@ class KeywordSearchResultFactory extends ChildFactory<KeyValueQuery> {
try {
String snippet;
String snippetQuery = null;
if (literal_query) {
@ -305,13 +308,14 @@ class KeywordSearchResultFactory extends ChildFactory<KeyValueQuery> {
}
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
// EDT threads, which can slow and/or hang the UI on large queries.
toPopulate.addAll(tempList);
//write to bb
//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)
@ -321,7 +325,8 @@ class KeywordSearchResultFactory extends ChildFactory<KeyValueQuery> {
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;
if (literal_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.
public Node createFlatNodeForKey(KeyValueQuery thing) {
return createNodeForKey(thing);
}
}
@Override
protected Node createNodeForKey(KeyValueQuery 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));
//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);
}
}
@ -448,22 +455,24 @@ class KeywordSearchResultFactory extends ChildFactory<KeyValueQuery> {
int resID = 0;
final KeywordSearchQuery origQuery = thing.getQuery();
List<KeyValueQuery> tempList = new ArrayList<>();
for (final AbstractFile f : uniqueMatches.keySet()) {
final int previewChunkId = uniqueMatches.get(f);
Map<String, Object> resMap = new LinkedHashMap<>();
if (f.getType() == TSK_DB_FILES_TYPE_ENUM.FS) {
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
// EDT threads, which can slow and/or hang the UI on large queries.
toPopulate.addAll(tempList);
//write to bb
new ResultWriter(matchesRes, origQuery, "").execute();
@ -480,7 +489,9 @@ class KeywordSearchResultFactory extends ChildFactory<KeyValueQuery> {
Node kvNode = new KeyValueNode(thingContent, Children.LEAF, Lookups.singleton(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);
}
}
@ -512,7 +523,8 @@ class KeywordSearchResultFactory extends ChildFactory<KeyValueQuery> {
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);
this.content = content;
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
*/
static class ResultWriter extends SwingWorker<Object, Void> {
@ -556,7 +568,8 @@ class KeywordSearchResultFactory extends ChildFactory<KeyValueQuery> {
});
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();
try {
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() {
@Override
@ -590,7 +604,8 @@ class KeywordSearchResultFactory extends ChildFactory<KeyValueQuery> {
final String snippetQuery = KeywordSearchUtil.escapeLuceneQuery(hit);
String snippet;
try {
snippet = LuceneQuery.querySnippet(snippetQuery, f.getId(), chunkId, !query.isLiteral(), true);
snippet = LuceneQuery
.querySnippet(snippetQuery, f.getId(), chunkId, !query.isLiteral(), true);
} catch (NoOpenCoreException e) {
logger.log(Level.WARNING, "Error querying snippet: " + snippetQuery, e);
//no reason to continie

View File

@ -25,6 +25,7 @@ import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.logging.Level;
import org.sleuthkit.autopsy.coreutils.Logger;
import org.sleuthkit.autopsy.coreutils.ModuleSettings;
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
class KeywordSearchSettings {
public static final String MODULE_NAME = "KeywordSearch";
static final String PROPERTIES_OPTIONS = MODULE_NAME+"_Options";
static final String PROPERTIES_NSRL = MODULE_NAME+"_NSRL";
static final String PROPERTIES_SCRIPTS = MODULE_NAME+"_Scripts";
static final String PROPERTIES_OPTIONS = MODULE_NAME + "_Options";
static final String PROPERTIES_NSRL = MODULE_NAME + "_NSRL";
static final String PROPERTIES_SCRIPTS = MODULE_NAME + "_Scripts";
private static boolean skipKnown = true;
private static final Logger logger = Logger.getLogger(KeywordSearchSettings.class.getName());
private static UpdateFrequency UpdateFreq = UpdateFrequency.DEFAULT;
private static List<StringExtract.StringExtractUnicodeTable.SCRIPT> stringExtractScripts = new ArrayList<StringExtract.StringExtractUnicodeTable.SCRIPT>();
private static Map<String,String> stringExtractOptions = new HashMap<String,String>();
private static List<StringExtract.StringExtractUnicodeTable.SCRIPT> stringExtractScripts
= new ArrayList<StringExtract.StringExtractUnicodeTable.SCRIPT>();
private static Map<String, String> stringExtractOptions = new HashMap<String, String>();
/**
* Gets the update Frequency from KeywordSearch_Options.properties
*
* @return KeywordSearchIngestModule's update frequency
*/
static UpdateFrequency getUpdateFrequency(){
if(ModuleSettings.getConfigSetting(PROPERTIES_OPTIONS, "UpdateFrequency") != null){
*/
static UpdateFrequency getUpdateFrequency() {
if (ModuleSettings.getConfigSetting(PROPERTIES_OPTIONS, "UpdateFrequency") != null) {
return UpdateFrequency.valueOf(ModuleSettings.getConfigSetting(PROPERTIES_OPTIONS, "UpdateFrequency"));
}
//if it failed, return the default/last known value
logger.log(Level.WARNING, "Could not read property for UpdateFrequency, returning backup value.");
return UpdateFrequency.DEFAULT;
}
/**
* Sets the update frequency and writes to KeywordSearch_Options.properties
*
* @param freq Sets KeywordSearchIngestModule to this value.
*/
static void setUpdateFrequency(UpdateFrequency freq){
static void setUpdateFrequency(UpdateFrequency freq) {
ModuleSettings.setConfigSetting(PROPERTIES_OPTIONS, "UpdateFrequency", freq.name());
UpdateFreq = freq;
}
/**
* Sets whether or not to skip adding known good files to the search during index.
* @param skip
*
* @param skip
*/
static void setSkipKnown(boolean skip) {
ModuleSettings.setConfigSetting(PROPERTIES_NSRL, "SkipKnown", Boolean.toString(skip));
skipKnown = skip;
}
/**
/**
* Gets the setting for whether or not this ingest is skipping adding known good files to the index.
*
* @return skip setting
*/
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"));
}
//if it fails, return the default/last known value
logger.log(Level.WARNING, "Could not read property for SkipKnown, returning backup value.");
return skipKnown;
//if it fails, return the default/last known value
logger.log(Level.WARNING, "Could not read property for SkipKnown, returning backup value.");
return skipKnown;
}
/**
* Sets what scripts to extract during ingest
*
* @param scripts List of scripts to extract
*/
static void setStringExtractScripts(List<StringExtract.StringExtractUnicodeTable.SCRIPT> scripts) {
stringExtractScripts.clear();
stringExtractScripts.addAll(scripts);
//Disabling scripts that weren't selected
for(String s : ModuleSettings.getConfigSettings(PROPERTIES_SCRIPTS).keySet()){
if (! scripts.contains(StringExtract.StringExtractUnicodeTable.SCRIPT.valueOf(s))){
for (String s : ModuleSettings.getConfigSettings(PROPERTIES_SCRIPTS).keySet()) {
if (!scripts.contains(StringExtract.StringExtractUnicodeTable.SCRIPT.valueOf(s))) {
ModuleSettings.setConfigSetting(PROPERTIES_SCRIPTS, s, "false");
}
}
//Writing and enabling selected scripts
for(StringExtract.StringExtractUnicodeTable.SCRIPT s : stringExtractScripts){
for (StringExtract.StringExtractUnicodeTable.SCRIPT s : stringExtractScripts) {
ModuleSettings.setConfigSetting(PROPERTIES_SCRIPTS, s.name(), "true");
}
}
/**
/**
* Set / override string extract option
*
* @param key option name 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);
ModuleSettings.setConfigSetting(PROPERTIES_OPTIONS, key, val);
}
/**
/**
* gets the currently set scripts to use
*
* @return the list of currently used script
*/
static List<SCRIPT> getStringExtractScripts(){
if(ModuleSettings.getConfigSettings(PROPERTIES_SCRIPTS) != null && !ModuleSettings.getConfigSettings(PROPERTIES_SCRIPTS).isEmpty()){
static List<SCRIPT> getStringExtractScripts() {
if (ModuleSettings.getConfigSettings(PROPERTIES_SCRIPTS) != null && !ModuleSettings
.getConfigSettings(PROPERTIES_SCRIPTS).isEmpty()) {
List<SCRIPT> scripts = new ArrayList<SCRIPT>();
for(Map.Entry<String,String> kvp : ModuleSettings.getConfigSettings(PROPERTIES_SCRIPTS).entrySet()){
if(kvp.getValue().equals("true")){
for (Map.Entry<String, String> kvp : ModuleSettings.getConfigSettings(PROPERTIES_SCRIPTS).entrySet()) {
if (kvp.getValue().equals("true")) {
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.");
return new ArrayList<SCRIPT>(stringExtractScripts);
}
/**
* get string extract option for the key
*
* @param key option name
* @return option string value, or empty string if the option is not set
*/
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);
}
else {
logger.log(Level.WARNING, "Could not read property for key "+ key + ", returning backup value.");
} else {
logger.log(Level.WARNING, "Could not read property for key " + key + ", returning backup value.");
return stringExtractOptions.get(key);
}
}
/**
* get the map of string extract options.
*
* @return Map<String,String> of extract options.
*/
static Map<String,String> getStringExtractOptions(){
Map<String,String> settings = ModuleSettings.getConfigSettings(PROPERTIES_OPTIONS);
if(settings == null){
Map<String,String> settingsv2 = new HashMap<String,String>();
logger.log(Level.WARNING, "Could not read properties for " + PROPERTIES_OPTIONS + ".properties, returning backup values");
static Map<String, String> getStringExtractOptions() {
Map<String, String> settings = ModuleSettings.getConfigSettings(PROPERTIES_OPTIONS);
if (settings == null) {
Map<String, String> settingsv2 = new HashMap<String, String>();
logger.log(Level.WARNING,
"Could not read properties for " + PROPERTIES_OPTIONS + ".properties, returning backup values");
settingsv2.putAll(stringExtractOptions);
return settingsv2;
}
else {
} else {
return settings;
}
}
/**
* 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.");
//setting default NSRL
if(!ModuleSettings.settingExists(KeywordSearchSettings.PROPERTIES_NSRL, "SkipKnown")){
logger.log(Level.INFO, "No configuration for NSRL found, generating default...");
KeywordSearchSettings.setSkipKnown(true);
}
//setting default Update Frequency
if(!ModuleSettings.settingExists(KeywordSearchSettings.PROPERTIES_OPTIONS, "UpdateFrequency")){
logger.log(Level.INFO, "No configuration for Update Frequency found, generating default...");
KeywordSearchSettings.setUpdateFrequency(UpdateFrequency.DEFAULT);
}
//setting default Extract UTF8
if(!ModuleSettings.settingExists(KeywordSearchSettings.PROPERTIES_OPTIONS, AbstractFileExtract.ExtractOptions.EXTRACT_UTF8.toString())){
logger.log(Level.INFO, "No configuration for UTF8 found, generating default...");
KeywordSearchSettings.setStringExtractOption(AbstractFileExtract.ExtractOptions.EXTRACT_UTF8.toString(), Boolean.TRUE.toString());
}
//setting default NSRL
if (!ModuleSettings.settingExists(KeywordSearchSettings.PROPERTIES_NSRL, "SkipKnown")) {
logger.log(Level.INFO, "No configuration for NSRL found, generating default...");
KeywordSearchSettings.setSkipKnown(true);
}
//setting default Update Frequency
if (!ModuleSettings.settingExists(KeywordSearchSettings.PROPERTIES_OPTIONS, "UpdateFrequency")) {
logger.log(Level.INFO, "No configuration for Update Frequency found, generating default...");
KeywordSearchSettings.setUpdateFrequency(UpdateFrequency.DEFAULT);
}
//setting default Extract UTF8
if (!ModuleSettings.settingExists(KeywordSearchSettings.PROPERTIES_OPTIONS,
AbstractFileExtract.ExtractOptions.EXTRACT_UTF8.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
if(!ModuleSettings.settingExists(KeywordSearchSettings.PROPERTIES_OPTIONS, AbstractFileExtract.ExtractOptions.EXTRACT_UTF16.toString())){
logger.log(Level.INFO, "No configuration for UTF16 found, generating defaults...");
KeywordSearchSettings.setStringExtractOption(AbstractFileExtract.ExtractOptions.EXTRACT_UTF16.toString(), Boolean.TRUE.toString());
}
if (!ModuleSettings.settingExists(KeywordSearchSettings.PROPERTIES_OPTIONS,
AbstractFileExtract.ExtractOptions.EXTRACT_UTF16.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
if(!ModuleSettings.settingExists(KeywordSearchSettings.PROPERTIES_SCRIPTS, SCRIPT.LATIN_1.name())){
logger.log(Level.INFO, "No configuration for Scripts found, generating defaults...");
ModuleSettings.setConfigSetting(KeywordSearchSettings.PROPERTIES_SCRIPTS, SCRIPT.LATIN_1.name(), Boolean.toString(true));
if (!ModuleSettings.settingExists(KeywordSearchSettings.PROPERTIES_SCRIPTS, SCRIPT.LATIN_1.name())) {
logger.log(Level.INFO, "No configuration for Scripts found, generating defaults...");
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.io.File;
import java.util.logging.Level;
import org.sleuthkit.autopsy.coreutils.Logger;
import javax.swing.JOptionPane;
import org.sleuthkit.datamodel.AbstractFile;
import org.sleuthkit.datamodel.FsContent;
import org.sleuthkit.datamodel.TskException;
@ -32,9 +35,10 @@ class KeywordSearchUtil {
public enum DIALOG_MESSAGE_TYPE {
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);
}
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;
if (type == DIALOG_MESSAGE_TYPE.ERROR) {
messageType = JOptionPane.ERROR_MESSAGE;
@ -126,7 +131,8 @@ class KeywordSearchUtil {
} else {
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;
} else {
return false;

View File

@ -21,6 +21,7 @@ package org.sleuthkit.autopsy.keywordsearch;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import org.sleuthkit.datamodel.BlackboardArtifact;
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.
-->
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
<!-- definition of simple elements -->
<xs:attribute name="name" type="xs:string"/>
<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="key" type="xs:string"/>
<xs:attribute name="created" >
<xs:attribute name="created">
<xs:simpleType>
<xs:restriction base="xs:string">
<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:element ref="keyword" minOccurs="0" maxOccurs="unbounded"/>
</xs:sequence>
<xs:attribute ref="created" use="required"/>
<xs:attribute ref="ingest_messages" default="true" use="optional"/>
<xs:attribute ref="modified" use="optional"/>
<xs:attribute ref="name" use="required"/>
<xs:attribute ref="use_for_ingest" default="true" use="optional"/>
<xs:attribute ref="created" use="required"/>
<xs:attribute ref="ingest_messages" default="true" use="optional"/>
<xs:attribute ref="modified" use="optional"/>
<xs:attribute ref="name" use="required"/>
<xs:attribute ref="use_for_ingest" default="true" use="optional"/>
</xs:complexType>
</xs:element>

View File

@ -24,6 +24,7 @@ import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.logging.Level;
import org.sleuthkit.autopsy.coreutils.Logger;
import org.apache.solr.client.solrj.SolrQuery;
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.
* By default, matches in all fields.
* By default, matches in all fields.
*/
class LuceneQuery implements KeywordSearchQuery {
@ -53,7 +54,7 @@ class LuceneQuery implements KeywordSearchQuery {
private String keywordStringEscaped;
private boolean isEscaped;
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 static final int MAX_RESULTS = 20000;
static final int SNIPPET_LENGTH = 50;
@ -62,12 +63,13 @@ class LuceneQuery implements KeywordSearchQuery {
static final String HIGHLIGHT_FIELD_REGEX = Server.Schema.CONTENT.toString();
//TODO use content_ws stored="true" in solr schema for perfect highlight hits
//static final String HIGHLIGHT_FIELD_REGEX = Server.Schema.CONTENT_WS.toString()
private static final boolean DEBUG = (Version.getBuildType() == Version.Type.DEVELOPMENT);
/**
* Constructor with query to process.
* @param keywordQuery
*
* @param keywordQuery
*/
public LuceneQuery(Keyword keywordQuery) {
this(keywordQuery.getQuery());
@ -76,6 +78,7 @@ class LuceneQuery implements KeywordSearchQuery {
/**
* Constructor with keyword string to process
*
* @param queryStr Keyword to search for
*/
public LuceneQuery(String queryStr) {
@ -88,7 +91,7 @@ class LuceneQuery implements KeywordSearchQuery {
public void addFilter(KeywordQueryFilter filter) {
this.filters.add(filter);
}
@Override
public void setField(String field) {
this.field = field;
@ -141,7 +144,8 @@ class LuceneQuery implements KeywordSearchQuery {
}
@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;
KeywordWriteResult writeResult = null;
@ -156,7 +160,8 @@ class LuceneQuery implements KeywordSearchQuery {
}
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
attributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_KEYWORD.getTypeID(), MODULE_NAME, termHit));
@ -186,9 +191,10 @@ class LuceneQuery implements KeywordSearchQuery {
return null;
}
/**
* Perform the query and return result
*
* @return list of ContentHit objects
* @throws NoOpenCoreException
*/
@ -212,7 +218,7 @@ class LuceneQuery implements KeywordSearchQuery {
sb.append(field).append(":").append(groupedQuery);
theQueryStr = sb.toString();
}
q.setQuery(theQueryStr);
q.setRows(MAX_RESULTS);
q.setFields(Server.Schema.ID.toString());
@ -286,26 +292,30 @@ class LuceneQuery implements KeywordSearchQuery {
/**
* 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 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
* @return
* @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
* @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 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 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 group whether the query should look for all terms grouped together in the query order, or not
* @return
* @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 group whether the query should look for all terms grouped together in the query order, or not
* @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();
String highlightField = null;
@ -318,7 +328,7 @@ class LuceneQuery implements KeywordSearchQuery {
SolrQuery q = new SolrQuery();
String queryStr = null;
if (isRegex) {
StringBuilder sb = new StringBuilder();
sb.append(highlightField).append(":");
@ -336,7 +346,7 @@ class LuceneQuery implements KeywordSearchQuery {
//always force grouping/quotes
queryStr = KeywordSearchUtil.quoteQuery(query);
}
q.setQuery(queryStr);
String contentIDStr = null;
@ -355,21 +365,20 @@ class LuceneQuery implements KeywordSearchQuery {
//q.setHighlightSimplePost("&raquo;"); //original highlighter only
q.setHighlightSnippets(1);
q.setHighlightFragsize(SNIPPET_LENGTH);
//tune the highlighter
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.post", "&laquo;"); //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
//docs says makes sense for the original Highlighter only, but not really
//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 {
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.
* 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
* so that you can simply view the stored text.
* so that you can simply view the stored text.
*/
interface MarkupSource {
/**
* @return text optionally marked up with the subsest of HTML that Swing
* components can handle in their setText() method.
*
*/
String getMarkup();
/**
*
* @return true if markup is marked to be searchable
*/
boolean isSearchable();
/**
* If searchable markup, returns prefix of anchor, otherwise return empty string
* @return
*
* @return
*/
String getAnchorPrefix();
/**
* if searchable markup, returns number of hits found and encoded in the markup
* @return
*
* @return
*/
int getNumberHits();
@ -58,80 +58,92 @@ interface MarkupSource {
*/
@Override
String toString();
/**
* get number pages/chunks
*
* @return number pages
*/
int getNumberPages();
/**
* get the current page number
*
* @return current page number
*/
int getCurrentPage();
/**
* Check if has next page
*
* @return true, if next page exists in the source
*/
boolean hasNextPage();
/**
* Move to next page
*
* @return the new page number
*/
int nextPage();
/**
/**
* Check if has previous page
*
* @return true, if previous page exists in the source
*/
boolean hasPreviousPage();
/**
* Move to previous page
*
* @return the new page number
*/
int previousPage();
/**
* Check if has next searchable item
*
* @return true, if next item exists in the source
*/
boolean hasNextItem();
/**
* Move to next item
*
* @return the new item number
*/
int nextItem();
/**
/**
* Check if has previous item
*
* @return true, if previous item exists in the source
*/
boolean hasPreviousItem();
/**
* Move to previous item
*
* @return the new item number
*/
int previousItem();
/**
* Get the current item number, do not change anything
*
* @return the current item number
*/
int currentItem();
/**
* 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
*/
LinkedHashMap<Integer,Integer> getHitsPages();
LinkedHashMap<Integer, Integer> getHitsPages();
}

View File

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

View File

@ -41,8 +41,11 @@ import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.logging.Level;
import org.sleuthkit.autopsy.coreutils.Logger;
import javax.swing.AbstractAction;
import org.apache.solr.client.solrj.SolrQuery;
import org.apache.solr.client.solrj.SolrServer;
import org.apache.solr.client.solrj.SolrServerException;
@ -133,8 +136,11 @@ class Server {
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
public static final long MAX_CONTENT_SIZE = 1L * 1024 * 1024 * 1024;
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 char ID_CHUNK_SEP = '_';
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 Process curSolrProcess = null;
private static Ingester ingester = null;
@ -160,7 +167,9 @@ class Server {
public enum CORE_EVT_STATES {
STOPPED, STARTED
};
}
;
private SolrServer solrServer;
private String instanceDir;
private File solrFolder;
@ -189,26 +198,34 @@ class Server {
private void initSettings() {
if (ModuleSettings.settingExists(PROPERTIES_FILE, PROPERTIES_CURRENT_SERVER_PORT)) {
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) {
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;
}
} else {
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)) {
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) {
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;
}
} else {
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");
}
}
if (br != null) {
if (br != null) {
try {
br.close();
} catch (IOException ex) {
@ -366,21 +383,21 @@ class Server {
final String loggingProperties = loggingPropertiesOpt + loggingPropertiesFilePath;
final String [] SOLR_START_CMD = {
javaPath,
MAX_SOLR_MEM_MB_PAR,
"-DSTOP.PORT=" + currentSolrStopPort,
"-Djetty.port=" + currentSolrServerPort,
"-DSTOP.KEY=" + KEY,
loggingProperties,
"-jar",
"start.jar"};
final String[] SOLR_START_CMD = {
javaPath,
MAX_SOLR_MEM_MB_PAR,
"-DSTOP.PORT=" + currentSolrStopPort,
"-Djetty.port=" + currentSolrServerPort,
"-DSTOP.KEY=" + KEY,
loggingProperties,
"-jar",
"start.jar"};
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(" ");
}
logger.log(Level.INFO, "Starting Solr using: " + cmdSb.toString());
curSolrProcess = Runtime.getRuntime().exec(SOLR_START_CMD, null, solrFolder);
logger.log(Level.INFO, "Finished starting Solr");
@ -409,7 +426,8 @@ class Server {
throw new KeywordSearchModuleException("Could not start Solr server process", ex);
}
} 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);
}
}
@ -465,20 +483,20 @@ class Server {
/**
* Tries to stop a Solr instance.
*
* <p/>
* Waits for the stop command to finish before returning.
*/
synchronized void stop() {
try {
logger.log(Level.INFO, "Stopping Solr server from: " + solrFolder.getAbsolutePath());
//try graceful shutdown
final String [] SOLR_STOP_CMD = {
javaPath,
"-DSTOP.PORT=" + currentSolrStopPort,
"-DSTOP.KEY=" + KEY,
"-jar",
"start.jar",
"--stop",
final String[] SOLR_STOP_CMD = {
javaPath,
"-DSTOP.PORT=" + currentSolrStopPort,
"-DSTOP.KEY=" + KEY,
"-jar",
"start.jar",
"--stop",
};
Process stop = Runtime.getRuntime().exec(SOLR_STOP_CMD, null, solrFolder);
logger.log(Level.INFO, "Waiting for stopping Solr server");
@ -532,7 +550,8 @@ class Server {
// TODO: check if SocketExceptions should actually happen (is
// probably caused by starting a connection as the server finishes
// 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());
return false;
} else {
@ -544,6 +563,7 @@ class Server {
return true;
}
/**
* ** Convenience methods for use while we only open one case at a time ***
*/
@ -769,13 +789,14 @@ class Server {
/**
* Execute solr query
*
* @param sq the query
* @param sq the query
* @param method http method to use
* @return query response
* @throws KeywordSearchModuleException
* @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) {
throw new NoOpenCoreException();
}
@ -824,7 +845,7 @@ class Server {
*
* @param content to get the text for
* @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
* @throws NoOpenCoreException
*/
@ -849,7 +870,7 @@ class Server {
* chunk as stored in Solr, e.g. FILEID_CHUNKID
*
* @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
*/
public static String getChunkIdString(long parentID, int childID) {
@ -860,7 +881,7 @@ class Server {
* Open a new core
*
* @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
*/
private Core openCore(String coreName, File dataDir) throws KeywordSearchModuleException {
@ -958,19 +979,24 @@ class Server {
try {
solrCore.add(doc);
} catch (SolrServerException ex) {
logger.log(Level.SEVERE, "Could not add document to index via update handler: " + doc.getField("id"), ex);
throw new KeywordSearchModuleException("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"),
ex);
throw new KeywordSearchModuleException(
"Could not add document to index via update handler: " + doc.getField("id"), ex);
} catch (IOException ex) {
logger.log(Level.SEVERE, "Could not add document to index via update handler: " + doc.getField("id"), ex);
throw new KeywordSearchModuleException("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"),
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
*
* @param contentID
* @param chunkID
* @return
* @return
*/
private String getSolrContent(long contentID, int chunkID) {
final SolrQuery q = new SolrQuery();
@ -1059,7 +1085,7 @@ class Server {
* Execute query that gets number of indexed file chunks for a file
*
* @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
* no chunks
* @throws SolrServerException
@ -1092,8 +1118,8 @@ class Server {
SolrServerNoPortException(int port) {
super("Indexing server could not bind to port " + port
+ ", port is not available, consider change the default "
+ Server.PROPERTIES_CURRENT_SERVER_PORT + " port.");
+ ", port is not available, consider change the default "
+ Server.PROPERTIES_CURRENT_SERVER_PORT + " port.");
this.port = port;
}

View File

@ -26,9 +26,12 @@ import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.logging.Level;
import org.sleuthkit.autopsy.coreutils.Logger;
import java.util.regex.Pattern;
import java.util.regex.PatternSyntaxException;
import org.apache.solr.client.solrj.SolrQuery;
import org.apache.solr.client.solrj.SolrServerException;
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 {
@ -61,7 +64,7 @@ class TermComponentQuery implements KeywordSearchQuery {
private final List<KeywordQueryFilter> filters = new ArrayList<KeywordQueryFilter>();
private String field = null;
private static int MAX_TERMS_RESULTS = 20000;
private static final boolean DEBUG = (Version.getBuildType() == Version.Type.DEVELOPMENT);
public TermComponentQuery(Keyword keywordQuery) {
@ -167,7 +170,8 @@ class TermComponentQuery implements KeywordSearchQuery {
}
@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;
//there is match actually in this file, create artifact only then
@ -193,7 +197,8 @@ class TermComponentQuery implements KeywordSearchQuery {
//preview
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
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();
q.setShowDebugInfo(DEBUG);
q.setTermsLimit(MAX_TERMS_RESULTS);
q.setTermsLimit(MAX_TERMS_RESULTS);
logger.log(Level.INFO, "Query: " + q.toString());
terms = executeQuery(q);
int resultSize = 0;
for (Term term : terms) {
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
logger.log(Level.INFO, "Regex # results: " + resultSize);

View File

@ -21,8 +21,8 @@ package org.sleuthkit.autopsy.keywordsearch;
import org.sleuthkit.datamodel.AbstractFile;
/**
*
*
*
*
*/
interface TextLanguageIdentifier {
@ -31,7 +31,7 @@ interface TextLanguageIdentifier {
* black board for the given {@code AbstractFile} as a TSK_TEXT_LANGUAGE
* 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.
* @return
*/

View File

@ -19,6 +19,7 @@
package org.sleuthkit.autopsy.keywordsearch;
import java.util.logging.Level;
import org.sleuthkit.autopsy.coreutils.Logger;
import org.sleuthkit.datamodel.AbstractFile;
import org.sleuthkit.datamodel.BlackboardArtifact;
@ -53,9 +54,11 @@ class TikaLanguageIdentifier implements TextLanguageIdentifier {
genInfo.addAttribute(textLang);
} 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
* limitations under the License.
*/
@HelpSetRegistration(helpSet = "keywordsearch-hs.xml", position = 3521)
package org.sleuthkit.autopsy.keywordsearch.docs;
@HelpSetRegistration(helpSet = "keywordsearch-hs.xml",
position = 3521) package org.sleuthkit.autopsy.keywordsearch.docs;
import org.netbeans.api.javahelp.HelpSetRegistration;

View File

@ -1,7 +1,7 @@
<?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">
<filesystem>
<!-- ======================================================
Actions
====================================================== -->
@ -10,22 +10,24 @@
<file name="org-sleuthkit-autopsy-keywordsearch-KeywordSearchConfigurationAction.instance"/>
<file name="org-sleuthkit-autopsy-keywordsearch-KeywordSearchAction.instance">
<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>
</folder>
</folder>
</folder>
<!-- ======================================================
Services
======================================================= -->
<folder name="Services">
<file name="org-sleuthkit-autopsy-keywordsearch-HighlightedMatchesSource.instance">
<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"/>
</file>
</folder>
<!-- ======================================================
Toolbars
====================================================== -->
@ -33,9 +35,10 @@
<folder name="Keyword">
<attr name="position" intvalue="104"/>
<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>
</folder>
</folder>
</filesystem>